Java JVM是否优化了不必要的自动装箱?
javac或JIT是否优化了不必要的自动装箱?假设我们有一个关于这段代码的例子Java JVM是否优化了不必要的自动装箱?,java,optimization,jvm,boxing,autoboxing,Java,Optimization,Jvm,Boxing,Autoboxing,javac或JIT是否优化了不必要的自动装箱?假设我们有一个关于这段代码的例子 for(int i=0; i<100000; i++) { f(i); } void f(Integer i) { System.out.println(i); } for(int i=0;iJVM可以自由地进行它喜欢的任何优化,因此一些JVM可能会对此进行优化 但是,假设它会这样做是一种不好的做法,对于每一个这样做的JVM,可能有几个不这样做 查看以下内容时,只需更改方法,使其接受与其内部
for(int i=0; i<100000; i++) {
f(i);
}
void f(Integer i) {
System.out.println(i);
}
for(int i=0;iJVM可以自由地进行它喜欢的任何优化,因此一些JVM可能会对此进行优化
但是,假设它会这样做是一种不好的做法,对于每一个这样做的JVM,可能有几个不这样做
查看以下内容时,只需更改方法,使其接受与其内部使用的相同装箱级别的类型。:
public class a
{
public static void main(String[] args)
{
for (int i = 0; i < 100000; i++)
f(i);
}
public static void f(Integer i)
{
System.out.println(i);
}
}
这个字节码告诉我们正在调用Integer.valueOf()
(main 9:
)但是,正如@Tim B所指出的,JVM内部发生的事情是另一件无法预测的事情。最好假设最坏的情况是JVM不会对其进行优化。OpenJDK和HotSpot JVM 5-8不会对它们进行优化,除非它们是未使用(即使如此也不总是)
但是,当您询问或回答这些问题时,有一种透视感是很重要的。与将数字转换为字符串的代码(JVM的操作方式)相比,自动生成是微不足道的,而与写入控制台相比,这是微不足道的这将节省99.99%以上的时间,因此在这里担心自动装箱就是担心错误的事情
在您的特定情况下,它无法优化自动装箱的方式,因为调用了PrintStream.println(Object)。JVM通常不了解库的功能,也不能假设调用PrintStream.println(int)我会做同样的事情。好吧,这是我在一次技术采访中遇到的问题,问这个问题的人希望得到具体的答案。我们谈论的是HotSpot JVM。我理解你的观点,并同意你的观点。javac
几乎没有优化功能,读取字节码并不能很好地测试优化时代码会这样做。那么内存效率呢?如果在每次调用中发生自动装箱,将有大约99873(100000-127)个不必要的整数实例被创建。我不同意我不应该担心自动装箱。但是我现在明白了为什么这种情况不会被优化,因为调用了println(Object)@Sebastian correct,我不是说它什么都不做,只是转换成文本的成本要高得多,而写入屏幕的成本要高得多。试着计时取println make与取整数make的差异。你不需要测量它,差异如此之大,你会看到差别。
Compiled from "a.java"
public class a {
public a();
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: ldc #2 // int 100000
5: if_icmpge 21
8: iload_1
9: invokestatic #3 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
12: invokestatic #4 // Method f:(Ljava/lang/Integer;)V
15: iinc 1, 1
18: goto 2
21: return
public static void f(java.lang.Integer);
Code:
0: getstatic #5 // Field java/lang/System.out:Ljava/io/PrintStream;
3: aload_0
4: invokevirtual #6 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
7: return
}