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

发布于 2024-10-20 20:29:57 字数 205 浏览 1 评论 0原文

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

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

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

I am looking at some disassembled code obtained from Java bytecode. I see some declaration as follows:

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

I am not able to figure out what the synthetic or access$0 mean. Can someone please help me understand this part?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

[旋木] 2024-10-27 20:29:57

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

In the java language, inner classes can access private members of their enclosing class. However, in Java bytecode, the concept of inner classes does not exist, and the private members are not accessible. To work around this, the compiler creates synthetic accessor methods in the outer class. I believe that is what you are seeing here. access$0 is simply the name of the method. I'm not sure what, if anything the synthetic does. It may just hide the method from other compilers to ensure encapsulation.

倚栏听风 2024-10-27 20:29:57

合成字段(2)

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

另请参阅 JavaTM 虚拟机规范 ( §4.7.6)Java 中的综合类

Synthetic field, (2)

A compiler-created field that links a local inner class to a block's local variable or reference type parameter.

See also The JavaTM Virtual Machine Specification (§4.7.6) or Synthetic Class in Java.

执手闯天涯 2024-10-27 20:29:57

assert 语句 JDK 1.8 案例研究

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

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;
    }
}

唯一“阻止”的就是在标识符上不使用美元的命名约定。另请参阅:何时应使用美元符号($) 在变量名中?

额外奖励:

static final int $assertionsDisabled = 0;

会起作用,因为与 Java 不同,字节码允许多个具有相同名称但不同类型的字段:名称相同但类型不同的变量

assert statement JDK 1.8 case study

The assert statement is an example of construct that generates a static synthetic field in Oracle JDK 1.8.0_45:

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

basically compiles to:

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();
            }
        }
    }
} 

This can be verified with:

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

which contains:

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

The synthetic field is generated so that Java only needs to call Assert.class.desiredAssertionStatus() once at load time, and it then caches the result there.

See also: https://stackoverflow.com/a/29439538/895245 for a more detailed explanation.

Note that this synthetic field can generate name conflicts with other fields we may define. E.g., the following fails to compile on Oracle JDK 1.8.0_45:

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

The only thing that "prevents" that is the naming convention of not using dollars on your identifiers. See also: When should I use the dollar symbol ($) in a variable name?

Bonus:

static final int $assertionsDisabled = 0;

would work, because unlike Java, the bytecode allows multiple fields with the same name but different types: Variables having same name but different type

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文