“静态合成”是什么意思?

时间:2011-03-07 17:54:44

标签: java bytecode disassembly java-synthetic-methods

我正在查看从Java字节码获得的一些反汇编代码。我看到一些声明如下:

.method static synthetic access$0()Lcom/package/Sample;

我无法弄清syntheticaccess$0的含义。有人可以帮我理解这部分吗?

3 个答案:

答案 0 :(得分:30)

在java语言中,内部类可以访问其封闭类的私有成员。但是,在Java字节码中,内部类的概念不存在,并且私有成员不可访问。要解决此问题,编译器会在外部类中创建合成访问器方法。我相信这就是你在这里看到的。 access$0只是方法的名称。我不确定synthetic是做什么的。它可能只是隐藏其他编译器的方法以确保封装。

答案 1 :(得分:26)

Synthetic field(2)

  

编译器创建的字段,用于将本地内部类链接到块的局部变量或引用类型参数。

另请参阅The JavaTM Virtual Machine Specification (§4.7.6)Synthetic Class in Java

答案 2 :(得分:4)

assert声明JDK 1.8案例研究

assert语句是在Oracle JDK 1.8.0_45中生成static synthetic字段的构造示例:

public class Assert {
    public static void main(String[] args) {
        assert System.currentTimeMillis() == 0L;
    }
}

基本上编译为:

public class Assert {
    // This field is synthetic.
    static final boolean $assertionsDisabled =
        !Assert.class.desiredAssertionStatus();
    public static void main(String[] args) {
        if (!$assertionsDisabled) {
            if (System.currentTimeMillis() != 0L) {
                throw new AssertionError();
            }
        }
    }
} 

可以通过以下方式验证:

javac Assert.java
javap -c -constants -private -verbose Assert.class

包含:

    static final boolean $assertionsDisabled;
  descriptor: Z
  flags: ACC_STATIC, ACC_FINAL, ACC_SYNTHETIC

生成合成字段,以便Java只需要在加载时调用Assert.class.desiredAssertionStatus()一次,然后将结果缓存在那里。

另请参阅:https://stackoverflow.com/a/29439538/895245以获取更详细的说明。

请注意,此合成字段可能会与我们可能定义的其他字段生成名称冲突。例如,以下无法在Oracle JDK 1.8.0_45上编译:

public class Assert {
    static final boolean $assertionsDisabled = false;
    public static void main(String[] args) {
        assert System.currentTimeMillis() == 0L;
    }
}

"唯一阻止"这是在标识符上不使用美元的命名约定。另见:When should I use the dollar symbol ($) in a variable name?

加成:

static final int $assertionsDisabled = 0;

可行,因为与Java不同,字节码允许多个具有相同名称但不同类型的字段:Variables having same name but different type