JIT可以进行此字段访问优化吗?

时间:2013-10-23 16:30:48

标签: java optimization garbage-collection jit

免责声明:请不要提出有关过早优化的建议。我很好奇。

想象一下,我想确保一个字段引用的某些对象可以尽快被垃圾收集。我正在使用像这样的自制单链表

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;
}

我在这里看不到任何不利之处,它使所有对象在原始代码中尽快收藏。

1 个答案:

答案 0 :(得分:2)

好的,优化器可以优化

while (bigData != null) {
    process(bigData);
    bigData = bigData.next;
}

BigData tmp = bigData;
while (tmp != null) {
    process(tmp);
    tmp = tmp.next;
}
bigData = null;

如果bigData字段不是volatileprocess方法没有禁止此优化的副作用。

但实际上,代码转换(如果有的话)看起来会完全不同。通常情况下,优化器会循环展开,创建执行一定次数迭代的代码块,并在进行向后跳转之前执行字段存储操作。因此垃圾收集器可以跳入某些“保存点”。但是如果process方法包含访问bigData字段的代码或者可能分配内存等,则会在每次执行之前执行字段存储调用