假设我在java中有一个方法调用站点。等效的 jvm 字节码是什么(除了转换为 invokevirtual/static 等的调用)?我对将接收器加载到堆栈上的命令更感兴趣。
-显然有一个命令已加载。
-另一个可能是另一个调用返回堆栈上的引用对象
-三、新指令。 (例如 new A().foo()。它被复制。但是复制的内容被构造函数消耗了)
-四,也许(??)Dup。 (当有 a.foo(); a.bar(); 时,编译器是否有机会生成 aload 然后 dup 而不是 aload aload?)
我最大的问题是其余的 dup 命令。因为他们对堆栈进行了洗牌。 javac什么时候产生它们?编译调用站点时是否使用它们?
我尝试查找文档,但没有成功。然后找到了源代码,但是需要几天的时间才能深入研究。我相信Code.java and Gen.java文件负责翻译/编译过程。
最佳答案
几乎任何产生引用的字节码指令都可以被javac用来加载接收器。
- aload、invokeX、new + dup
那些你已经提到过的。 getfield、getstatic
field.method();
aa加载
arr[index].method();
新数组
(new Object[0]).hashCode();
多重数组
(new byte[5][10]).getClass();
检查
((List) obj).size();
最不发达国家
MyClass.class.getName();
aconst_null
((Object) null).getClass();
重复
IntSupplier s = field::hashCode;
此处使用
dup
+invokevirtual
发出棘手的空检查:getstatic #2 // Field field:Ljava/lang/String; dup invokevirtual #3 // Method java/lang/Object.getClass:()Ljava/lang/Class; pop invokedynamic #4, 0 // InvokeDynamic #0:getAsInt
关于Javac 实现 : What jvm instructions does a method call produce?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53883111/