Java优化:局部变量与实例变量

时间:2013-10-09 09:41:29

标签: java garbage-collection compiler-optimization

在Java中,如果我有很多本地对象,如果我将它们定义为实例变量,它会运行得更快吗?例如,如果多次调用我的func1(),比如在循环中调用,那么每次调用函数时,JVM是否会继续实例化并垃圾收集list2?相反,我应该重用相同的list1对象来防止垃圾收集和实例化开销吗?

class A {
   List list1 = new ArrayList();
   private void func1() {
      list1.clear();
      // add new objects list1

      List list2 = new ArrayList();
      // add new objects to list2
   }
}

优化器是否足够智能以跳过垃圾收集并自动重用该对象?

5 个答案:

答案 0 :(得分:2)

GC优化不是决定Local vs Instance变量的正确方法。如果需要的变量由多个实例方法使用,那么使用实例变量是有意义的。

你是对的,局部变量使用可能会增加GC活动。

答案 1 :(得分:1)

在决定是使用本地变量还是实例变量之前,可能需要考虑各种用例。性能可能因用例而异。

Effective Java中可以找到一个很好的例子:Item 5 - “避免创建不必要的对象

答案 2 :(得分:1)

还要考虑实例变量值的线程安全性。同一对象的两个线程需要同步访问实例变量数据,但在这里它始终是一个新的局部变量数据对象。

答案 3 :(得分:1)

如果 - 且仅 - 您已证实,由于对象创建而导致GC出现问题,您应该考虑合并已验证的对象成本高昂。

为此,你不必重新发明任何轮子,你可以使用Javolutions utils来实现它,FastList在这种情况下使用FastList.newInstance()调用:

List<Whatever> newOrReusedList = FastList.newInstance();

...以及相应的FastList.recycle(FastList)调用,以使其可供重复使用。 (谢谢 @JIV ,我忘了添加这一点。)

(请注意,使用javolutions Fast *类可能会导致不同的性能:它们面向可预测的性能(实时系统)而不是速度,因此可能存在用例,当它们的执行速度比java.lnag的速度慢时)

答案 4 :(得分:1)

我用jdk1.6编写了一个小测试程序,在

下面

结果:
* dostuff为594ms(创建本地)
* dostuff2的58ms(使用实例)

public class Test {

static long counter=0;
public static void main(String[] args) {
    long t1  = System.nanoTime();
    Test test = new Test();
    for (int i=0;i<1000000000;i++) {
        test.doStuff();//or dostuff2
    }
    long t2  = System.nanoTime();
    System.err.println((t2-t1)/1000000);
    System.err.println(counter); // to check it wasnt optimised away
}

private void doStuff() {
    List l = new ArrayList();
    if (l!=null) {
        counter++;
    }
}

List l2 = new ArrayList();
private void doStuff2() {
    if (l2!=null) {
        counter++;
    }
}
}

结果,似乎实例比使用本地更快,正如人们所期望的那样。

然而,似乎你至少在我的电脑上节省了大约0.5亿美元的物品,所以你需要真正需要性能增益来证明它的合理性