免责声明:请不要就过早优化提出建议。我只是好奇。
想象一下,我想确保字段引用的某些对象可以尽快被垃圾收集。我正在使用像这样的自制单链表
class BigData {
byte[] someBigArray;
BigData next;
}
private BigData bigData;
并像这样迭代
while (bigData != null) {
process(bigData);
bigData = bigData.next;
}
JIT 是否可以随意更改它,如下所示?
BigData tmp = bigData;
while (tmp != null) {
process(tmp);
tmp = tmp.next;
}
bigData = null;
假设没有其他对任何实例的引用BigData
。认为process
是一个不访问该字段的简单内联方法bigData
。两个片段是等效的(假设中间没有抛出异常),唯一的区别是第二个片段将字段访问从循环移到了外部。
重复免责声明:请不要就过早优化提出建议。我只是好奇。
回复评论“即使 JIT 所做的就是你‘想要’的改变,为什么这会让 GC 更快/更快地收集它们呢?”:如果JIT做了改变,那么所有的大对象只能在循环之后被收集。如果没有,则每次循环前进时,都会有一个对象符合 GC 的条件。
附录:
实际上,只要 JIT 可以自由地执行上述转换,它就可以执行以下转换:
BigData tmp = bigData;
bigData = null;
while (tmp != null) {
process(tmp);
tmp = tmp.next;
}
我在这里看不到任何缺点,它使所有对象在原始代码中都可以收集。
嗯,优化器can优化
while (bigData != null) {
process(bigData);
bigData = bigData.next;
}
into
BigData tmp = bigData;
while (tmp != null) {
process(tmp);
tmp = tmp.next;
}
bigData = null;
if the bigData
字段不是volatile
和process
方法没有禁止这种优化的副作用。
但在实践中,代码转换(如果有的话)看起来会完全不同。通常,优化器会展开循环,创建一个执行一定次数迭代的代码块,并在向后跳转之前执行字段存储操作。因此,存在垃圾收集器可以跳入的某些“保存点”。但是如果process
方法包含访问的代码bigData
字段或可能分配内存等,字段存储将在每次调用之前执行。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)