对象,堆或堆栈中的原语?

时间:2014-09-01 01:26:06

标签: java object stack heap primitive

大多数人说对象中的原语存储在Heap中,但是,我从以下性能测试中得到了不同的结果:

public class Performance {

long sum = 0;

public static void main(String[] args) {
    // TODO Auto-generated method stub
    long startTime = System.currentTimeMillis();
    long pSum = 0;
    for(int i = 0; i < Integer.MAX_VALUE; i++){
        pSum += i;

    }
    long endTime = System.currentTimeMillis();
    System.out.println("time of using primitive:" + Long.toString(endTime - startTime));
    System.out.println(pSum);

    long startTime1 = System.currentTimeMillis();
    Long Sum = 0L;
    for(int i = 0; i < Integer.MAX_VALUE; i++){
        Sum += i;
    }
    long endTime1 = System.currentTimeMillis(); 
    System.out.println("time of using object:" + Long.toString(endTime1 - startTime1));
    System.out.println(Sum);

    Performance p = new Performance();
    long startTime2 = System.currentTimeMillis();
    for(int i = 0; i < Integer.MAX_VALUE; i++){
        p.sum += i;
    }
    long endTime2 = System.currentTimeMillis();
    System.out.println("time of using primitive in object:" + Long.toString(endTime2 - startTime2));
    System.out.println(p.sum);
}

}

结果如下:

time of using primitive:1454
2305843005992468481
time of using object:23870
2305843005992468481
time of using primitive in object:1529
2305843005992468481

我们可以在对象中找到使用原语和使用原语的时间几乎相同。所以如果对象中的原语存储在Heap中,我会感到困惑。为什么在对象中使用原语和使用原语的时间成本几乎相同?

1 个答案:

答案 0 :(得分:1)

当你去

Long sum;
...
sum += 1;
从理论上讲,JVM每次都会分配一个新的Long,因为 Longs是不可变的。现在,一个非常聪明的编译器可以在这里做一些聪明的事情,但这解释了为什么你的第二个循环的时间要大得多。它正在分配Integer.MAXINT新的Sum对象。 Autoboxing的另一个原因是棘手的。

另外两个循环不需要分配新对象。一个使用原始int,而在另一个中,您可以增加Performance.sum,而无需每次都分配新的性能。如图所示,访问堆栈或堆中的原始int应该大致相同。

您的计时与堆与堆栈访问速度的关系很少,但与循环中分配大量对象的所有相关。

正如其他人所指出的那样,微观基准可能会产生误导。