2011-03-07 89 views
21

我正在查看从Java字节码中获得的一些反汇编代码。我看到一些声明如下:“静态合成”是什么意思?

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

我无法弄清楚什么syntheticaccess$0意思。有人能帮我理解这个部分吗?

+2

我不能相信这是不自然! – Mehrdad 2011-03-07 17:57:20

回答

26

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

2

在Oracle JDK 1.8.0_45断言是产生static synthetic字段的一个示例:

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

基本上编译为:

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

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

这可以与被验证

其中包含:

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

合成字段使得爪哇只需要在加载时调用一次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