Java中的内存效率

时间:2012-05-26 18:36:25

标签: java optimization memory jvm

关于内存使用和变量实例化哪个更好或没有区别:

for(int i = 0; i < someValue; i++)
{
    Obj foo = new Obj();
    Use foo.....
}

相反:

Obj foo;

for(int i = 0; i < someValue; i++)
{
    foo = new Obj();
    Use foo.....
}

6 个答案:

答案 0 :(得分:11)

没有区别。内存使用方面的任何潜在差异都将由编译器优化。

如果您编译(使用javap -c)这两个示例并比较字节码,您会发现字节码是相同的。当然,这取决于JVM版本。但是,由于这个例子是如此微不足道,因此可以安全地假设它们的内存效率都不高于另一个。


示例1:

代码:

public class example1 {
    public static void main(String[] args) {
        for (int i=0; i<10; i++) {
            Object a = new Object();
        }
    }
}

字节码:

public class example1 extends java.lang.Object{
public example1();
  Code:
   0:   aload_0
   1:   invokespecial   #1; //Method java/lang/Object."<init>":()V
   4:   return

public static void main(java.lang.String[]);
  Code:
   0:   iconst_0
   1:   istore_1
   2:   iload_1
   3:   bipush  10
   5:   if_icmpge       22
   8:   new     #2; //class java/lang/Object
   11:  dup
   12:  invokespecial   #1; //Method java/lang/Object."<init>":()V
   15:  astore_2
   16:  iinc    1, 1
   19:  goto    2
   22:  return
}

示例2:

代码:

public class example2 {
    public static void main(String[] args) {
        Object a;
        for (int i=0; i<10; i++) {
            a = new Object();
        }
    }
}

字节码:

public class example2 extends java.lang.Object{
public example2();
  Code:
   0:   aload_0
   1:   invokespecial   #1; //Method java/lang/Object."<init>":()V
   4:   return

public static void main(java.lang.String[]);
  Code:
   0:   iconst_0
   1:   istore_2
   2:   iload_2
   3:   bipush  10
   5:   if_icmpge       22
   8:   new     #2; //class java/lang/Object
   11:  dup
   12:  invokespecial   #1; //Method java/lang/Object."<init>":()V
   15:  astore_1
   16:  iinc    2, 1
   19:  goto    2
   22:  return
}

答案 1 :(得分:6)

现代JVM的工作方式都相同,编译器优化也会使两者相同。

忽略编译器优化和现代JVM,第一种方法更好。

答案 2 :(得分:5)

第一个例子在对象范围方面最有意义,但两者都应该像另一个一样具有内存效率。

答案 3 :(得分:5)

您的示例之间没有区别,正如其他答案所指出的那样。但是,问题是:如果你的例子很慢,你应该怎么做?

如果要在真正的性能关键部分减少分配/垃圾收集所花费的时间,请考虑重复使用对象,而不是在每次迭代时分配新对象。

foo = new Obj();
for(int i = 0; i < someValue; i++)
{
    foo.init(i);
    Use foo.....
}

来自java performance tuning(一本旧书,但在现代的jvm:s和.NET clr中也是如此)

  

......对象的创建成本很高。哪里   重复使用同一个对象是合理的,你应该这样做。你需要   要注意什么时候不要打电话给新人。一个相当明显的情况是   当你已经使用了一个物体并且可以在它之前丢弃它   即将创建同一个类的另一个对象。你应该看看   对象并考虑是否可以重置字段和   然后重用该对象,而不是扔掉它并创建另一个。   这对于经常出现的对象尤为重要   使用和丢弃

答案 4 :(得分:3)

编译器优化将使两者相同。但是,如果您忽略编译器优化,我更喜欢第一种方法。更重要的是,即使Joshua Bloch也建议在Effective Java中这样做(很好的阅读)。

答案 5 :(得分:1)

编译器应该为您优化这一点。我更喜欢第一个,因为它更具可读性。让Object foo具有更大的范围可能会引起混淆。