Android内存优化(一)字符串优化

Eclipse Memory Analyzer(1.12.0)

Demo地址

字符串冗余

某些情况下内存中存在大量重复字符串对象,下面是简单的案例

data1中存放的是字符串常量池中”aaa…aaa”的引用;data2中存放的是堆中字符串”bbb…bbb”的引用;data3中存放的是字符串常量池”ccc…ccc”的地址。

class MainActivity : AppCompatActivity() {
    lateinit var binding: ActivityMainBinding
    val data1: Array<String?> = arrayOfNulls(1000)
    val data2: Array<String?> = arrayOfNulls(1000)
    val data3: Array<String?> = arrayOfNulls(1000)

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)
    }

    override fun onResume() {
        super.onResume()
        binding.button.setOnClickListener {
            Log.i(TAG, "onResume: 填充数据")
            for (i in data1.indices) {
                data1[i] =
                    "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
            }
            for (i in data2.indices) {
                val str =
                    StringBuilder("bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb")
                data2[i] = str.toString()
            }
            for (i in data3.indices) {
                val str =
                    StringBuilder("cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc")
                data3[i] = str.toString().intern()
            }
            Log.i(TAG, "onResume: 填充完毕")
        }

    }

}
复制代码
  • 通过mat查看data1,data2,data3在内存中情况,图中Shallow Heap表示对象本身占用内存,Retained Heap 表示当前对象释放可以获取多少内存,可以看出通过String.intern可以显著减少字符串冗余对象

·

寻找冗余的字符串对象

  • 借助Eclipse Memory Ananlyer打开已经被hprof-conv.exe转换成标准格式的hprof文件
  • 在Overview界面进行如下操作

  • 在Group By Value中的objects输入java.lang.String,然后Finish

  • 借助Objects排序,就可找到重复最多的字符对象

确定字符串对象使用位置

方式一

  • Merge Shortest Paths to GC Roots > exclude all phantom/weak/soft etc.references

  • GC 路径

方式二

  • 通过List objects>with incoming references 确定当前字符串对象被那些对象引用

  • 引用情况,通过图中的引用情况就可分析出字符串对象被存放在data2[0]处。

使用String#intern减少内存

注意String#intern使用频率,它会向字符串常量池中添加字符串。String#intern进一步学习请看参考内容。

参考内容

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享