首页 > 解决方案 > 我想知道如何编写初始化静态类变量的Java字节码

问题描述

我现在正在研究 Java 字节码。我想编写 Java 字节码以在 Java 源代码中制作 Test.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。我想知道如何在 static {} 中编写 java 字节码;代码:0:iconst_1 1:putstatic #2 //字段a:I 4:返回

对不起,奇怪的英语句子。谢谢你让我知道。

标签: javabytecode

解决方案


为了完整起见,静态字段的初始化器行为不是编译时常量,在 Java 语言规范中描述为类初始化的第 9 步:

接下来,按文本顺序执行类的类变量初始化程序和静态初始化程序,或者接口的字段初始化程序,就好像它们是一个单独的块一样。

此块javap打印为static {},隐藏您感兴趣的实现细节。

对于这个细节,我们必须参考 Java 虚拟机规范,§2.9.2.,类初始化方法

如果满足以下所有条件,则方法是类或接口初始化方法

  • 它有一个特殊的名字<clinit>
  • 它是void§4.3.3)。
  • [...] 该方法ACC_STATIC设置了它的标志并且不接受任何参数(第 4.6 节)。

我省略了有关在旧 JVM 中未强制执行哪些属性的详细信息,因为您不应该利用这些缺陷。类初始值设定项应始终具有上面指定的属性。

一般而言,Java 虚拟机规范是您在处理 Java 字节码时应该随时准备的文档。


推荐阅读