【问题标题】:What is the meaning of "static synthetic"?“静态合成”是什么意思?
【发布时间】:2011-07-10 13:04:35
【问题描述】:

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

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

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

【问题讨论】:

  • 我不敢相信这不自然!

标签: java bytecode disassembly java-synthetic-methods


【解决方案1】:

Synthetic field, (2)

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

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

【讨论】:

    【解决方案2】:

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

    【讨论】:

      【解决方案3】:

      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

      【讨论】:

        猜你喜欢
        • 2017-03-18
        • 1970-01-01
        • 1970-01-01
        • 2011-01-19
        • 2017-08-13
        • 1970-01-01
        • 1970-01-01
        • 2010-10-26
        • 2011-10-28
        相关资源
        最近更新 更多