我现在正在研究Java字节码。 我想编写 Java 字节码来制作 Test.java 在 java 源代码中,如下所示。 我想在类中声明和初始化静态变量。
测试.java
public class Test {
public static int a=1;
public Test() {
}
public static void main(String[] var0) {
}
}
命令结果:javap -c 测试
public class Test {
public static int a;
public Test();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String[]);
Code:
0: return
**static {};
Code:
0: iconst_1
1: putstatic #2 // Field a:I
4: return**
}
我正在编写的代码
测试.j
.class public Test
.super java/lang/Object
.field public static a I
.method public <init>()V
aload_0
invokenonvirtual java/lang/Object/<init>()V
return
.end method
.method public static main([Ljava/lang/String;)V
.limit stack 32
.limit locals 32
return
.end method
我使用 jasmin-2.4 将 java 字节码转换为 .class。 我想知道如何在静态{}中编写java字节码; 法典: 0: iconst_1 1: 放置 #2//字段 a:I 4:返回
对不起,奇怪的英语句子。 如果你让我知道,谢谢你。
为了完整起见,静态字段的初始值设定项的行为不是编译时常量,描述为 Java 语言规范中类初始化的步骤 9:
接下来,按文本顺序执行类的类变量初始值设定项和静态初始值设定项,或接口的字段初始值设定项,就好像它们是单个块一样。
此块是javap
打印为static {}
,隐藏您感兴趣的实现细节。
对于这个细节,我们必须参考 Java 虚拟机规范 §2.9.2.,类初始化方法:
如果满足以下所有条件,则方法就是类或接口初始化方法:
- 它具有特殊名称
<clinit>
.- 它是
void
(§4.3.3(。- [...]该方法设置了
ACC_STATIC
标志,并且不带参数(§4.6(。
我省略了有关旧版 JVM 中未强制执行哪些属性的详细信息,因为您不应该利用这些缺陷。类初始值设定项应始终具有上面指定的属性。
通常,Java 虚拟机规范是您在处理 Java 字节码时应始终拥有的文档。