最终引用的优化在java中是如何工作的?
我一直在试图弄清楚Java优化的所有方面,并发现了一些有趣的东西
第一种情况:原语类型编译时优化
public class Clazz {
public static void main(String args[]) {
final int i = 300;
new Clazz() {
void foo() {
System.out.println(i);
}
}.foo();
}
}
编译后(我使用jd-gui-0.3.5.windows
来反编译二进制文件),它看起来像:
public class Clazz {
public static void main(String[] args) {
int i = 300;
new Clazz() {
void foo() {
System.out.println(300);
}
}.foo();
}
}
正如所料,不是吗^编译后,{
第二种情况:非原语类型编译时优化
public class Clazz {
public static void main(String args[]) {
final Integer i = 300; // replaced int with Integer
new Clazz() {
void foo() {
System.out.println(i);
}
}.foo();
}
}
汇编后:
public class Clazz {
public static void main(String[] args) {
Integer i = Integer.valueOf(300);
new Clazz() {
void foo() {
System.out.println(Clazz.this);
}
}.foo();
}
}
问题:
在这种情况下Clazz.this
是什么?我知道,它是对Clazz
的封闭实例的引用,但在这种情况下它不应该工作!我需要打印i
,但编译器建议我打印Clazz.this
,而不是打印它,它可以工作!有什么问题?jd-gui
是否反编译错误,或者我是否遗漏了Java编译和优化方面的内容
UPD:
{
class Clazz$1 extends Clazz {
Clazz$1(Integer paramInteger) {}
void foo() {
System.out.println(this.val$i);
}
}
# 1 楼答案
您只需查看字节码(
javap -c Clazz$1.class
)与
int i = 300
一起:与
Integer i = 300
一起:因此
int
是内联的,而Integer
不是内联的另外,这是我从jd gui(3.0.5)获得的信息:
# 2 楼答案
jd-gui
正在错误地反编译代码在我的JVM上,匿名类的反汇编代码如下所示:
正如您所看到的,
i
的副本存储在匿名类中,位于名为val$i
的字段中(名称是特定于实现的)反编译器似乎错误地将此字段呈现为
Clazz.this
# 3 楼答案
这应该是一种最接近的方法,
jd-gui
无法解释Integer
对象在调用System.out.println
时如何装箱其值。反编译算法本身必须假定对这个Integer
对象最重要的引用是什么,并选择Clazz.this
的结果