Eclipse Memory Analyzer(1.12.0)
字符串冗余
某些情况下内存中存在大量重复字符串对象,下面是简单的案例
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