我在Java字节码中理解LookUpSwitch和TableSwitch有些困难.
如果我理解得很好,LookUpSwitch和TableSwitch都对应于switchJava源代码的声明?为什么一个JAVA语句生成2个不同的字节码?
每个Jasmin文档:
我正在尝试为学术研究实现Java的一个子集.好吧,我处于最后阶段(代码生成),我编写了一个相当简单的程序来查看如何处理方法参数:
class Main {
public static void main(String[] args) {
System.out.println(args.length);
}
}
Run Code Online (Sandbox Code Playgroud)
然后我构建了它,并通过我在以下网址找到的在线反汇编程序运行'Main.class':http: //www.cs.cornell.edu/People/egs/kimera/disassembler.html
我得到了'main'方法的以下实现:(反汇编输出在Jasmin中)
.method public static main([Ljava/lang/String;)V
.limit locals 1
.limit stack 2
getstatic java/lang/System/out Ljava/io/PrintStream;
aload_0
arraylength
invokevirtual java/io/PrintStream.println(I)V
return
.end method
Run Code Online (Sandbox Code Playgroud)
我的问题是:
1.aload_0应该将'this'推送到堆栈(这就是JVM规范似乎说的)
2.arraylength应该返回引用位于堆栈顶部的数组的长度
所以根据我的说法,1和2的组合甚至不应该起作用.
它是如何/为什么有效?或者是反汇编工具,实际的字节码是别的吗?
我试图在java字节码中做一些错误处理.我首先尝试实现一些类似catch的子例程,在那里我将检查错误情况,并跳转到相应的子例程,有点像:
iconst_1
iconst_0
dup
ifeq calldiverr
goto enddivtest
calldiverr:
jsr divError
enddivtest:
idiv
...More instructions...
divError:
getstatic java/lang/System/out Ljava/io/PrintStream;
ldc "Oh dear you divided by 0!"
invokevirtual java/io/PrintStream/print(Ljava/lang/String;)V
Run Code Online (Sandbox Code Playgroud)
上面的问题是当我有多个指令跳转到这个子程序时,我在运行字节码时收到一条错误信息,说堆栈高度不一致.
也许使用例外是解决这个问题的最佳方法?
通过一些谷歌搜索,我发现你可以创建Exception类的实例,并用以下内容初始化它们:
new java/lang/Exception
dup
ldc "exception message!"
invokespecial java/lang/Exception/<init>(Ljava/lang/String;)V
Run Code Online (Sandbox Code Playgroud)
我也发现你可以扔它们,athrow这似乎没问题.
然而令我感到困惑的是如何捕获异常.似乎有一个神奇的"异常表"将异常的抛出和捕获粘在一起,但我不知道如何从头开始编写字节码(以及使用Jasmin进行汇编)时定义其中一个.有人可以告诉我创建异常表的秘诀吗?并且可能给我一个与jasmin汇编的异常处理示例?
为什么字节码生成为
.annotation system Ldalvik/annotation/Throws;
value = {
Ljava/io/FileNotFoundException;
}
.end annotation
Run Code Online (Sandbox Code Playgroud)
而不是.throws Ljava/io/FileNotFoundException
throws FileNotFoundException如果一个方法在java代码的标头中声明?
我正在编写一个生成 Jasmin 代码的编译器,并希望调用一个以 Class 作为参数的方法。
public class CTest
{
public static void main(String[] args)
throws Exception
{
java.lang.reflect.Array.newInstance(CTest.class, 0);
}
}
Run Code Online (Sandbox Code Playgroud)
所以在 Jasmin 中,我认为应该是:
.class public CTest2
.super java/lang/Object
.method public static main([Ljava/lang/String;)V
.limit stack 2
.limit locals 1
ldc_w CTest2
iconst_0
invokestatic java/lang/reflect/Array/newInstance(Ljava/lang/Class;I)Ljava/lang/Object;
pop
return
.end method
Run Code Online (Sandbox Code Playgroud)
当我组装并运行它时,我得到:
线程“main”中的异常 java.lang.VerifyError: (类: CTest2, 方法: main 签名: ([Ljava/lang/String;)V) 常量池中的非法类型
使用“javap -c -verbose”查看 CTest.class(Java 版本)和 CTest2.class(Jasmin 版本)的反汇编代码,它们似乎都以相同的方式设置常量池:
const #2 = class #16; // CTest
const #16 = Asciz CTest;
0: ldc_w #2; …Run Code Online (Sandbox Code Playgroud) 我使用Jasmin Java汇编程序编译玩具语言.但是当我使用jsr指令递归回子程序,并使用java运行Jasmin的输出时,我收到错误"递归调用jsr条目".这是Jasmin代码(它是计算5!(我已经省略了类定义;所有这些都在主方法体中)):
f:
swap
istore 2
iload 2
ifeq label0
iload 2
iload 2
ldc 1
isub
jsr f
istore 1
istore 2
iload 1
iload 2
imul
goto label1
label0:
ldc 1
label1:
swap
astore 0
ret 0
main:
ldc 5
jsr f
istore 1
iload 1
Run Code Online (Sandbox Code Playgroud) 我试图像这样在Jasmin中实例化一个类:
new Ljava/lang/Object;
dup
invokespecial java/lang/Object/<init>()V
Run Code Online (Sandbox Code Playgroud)
这确实编译但是类vierifier抱怨:
"VerifyError:调用错误的初始化方法."
实例化一个类的正确方法是什么?
这里说:
Since 2.1 :
[..]
added the invokedynamic instruction
Run Code Online (Sandbox Code Playgroud)
因此,我认为可以用jasmin编写包含invokedynamics的指令代码.但是我找不到关于jasmin语法的任何文档,我只是想出了如何使用invokedynamic来获取Jasmin的VerifyErrors,而不是如何创建一个工作示例.
如何在Jasmin中正确使用该指令?