Javap 输出 : difference static {} and public {}

标签 java jvm bytecode bytecode-manipulation jvm-bytecode

我有两个示例类文件,一个来自示例 Java 应用程序,一个来自示例 C 应用程序(使用 LLJVM 编译为字节码)。

查看它们的输出,我可以通过 javap -c -p 看到用于初始化(静态)字段的 Java 应用程序显示以下 block :

static {};
Code: 
0: sipush 1339
3: putstatic   #7     //Field SRV_ID
etc

这基本上是 <clinit>方法,如果我理解的话。或者被我正在使用的虚拟机检测到。

但是 C-app 有这个:

public {};
Code: 
0: sipush 1339
3: putstatic   #7     //Field SRV_ID
etc

这是什么?我的 VM 没有检测到它。

示例类文件。 第一个来自打印消息并等待 20 秒的 Java 应用程序,重复。 第二个是功能大致相同的 C 应用程序。

http://www.fast-files.com/getfile.aspx?file=156962

http://www.fast-files.com/getfile.aspx?file=156961

很抱歉以这种方式进行 - 我不会立即知道如何附加文件或有效地显示 .class 文件。

最佳答案

这似乎是一个非标准声明 javap没考虑。通常,static初始化程序被编译为名为 <clinit> 的字节码方法有一个static修饰符。显然,javap通过仅打印修饰符的人类可读形式并省略 <clinit> 来解码它们姓名。

在这里,它遇到了一个名为 <clinit> 的方法并拥有 public修饰符(没有 static 修饰符),就像往常一样,打印修饰符并省略 <clinit>姓名。

LLJVM 生成的代码似乎依赖于 old oddity :

In a class file whose version number is 51.0 or above, the method must additionally have its ACC_STATIC flag (§4.6) set in order to be the class or interface initialization method.

This requirement was introduced in Java SE 7. In a class file whose version number is 50.0 or below, a method named <clinit> that is void and takes no arguments is considered the class or interface initialization method regardless of the setting of its ACC_STATIC flag.

对我来说,在以前的版本中看到 ACC_STATIC 确实令人惊讶。修饰符不是强制性的,我看不出有任何理由利用这种奇怪之处。类初始值设定项(在 Java 中声明为 static {})应该具有 ACC_STATIC 似乎很自然。标志,我什至无法想象省略的 ACC_STATIC 的假定语义旗帜。这意味着应该发生两件奇怪的事情之一,a)尽管没有 ACC_STATIC,但它在没有实例的情况下被调用。标志(被调用就像拥有它一样)或 b)它被一个必须“神奇地”创建的实例调用。

specification关于任何非标准 <clinit> 的说明如下方法:

Other methods named <clinit> in a class file are of no consequence. They are not class or interface initialization methods. They cannot be invoked by any Java Virtual Machine instruction and are never invoked by the Java Virtual Machine itself.

关于Javap 输出 : difference static {} and public {},我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49259422/

相关文章:

java - 最快的 Java 字符串查找集合?

java - 无法解决部署 JSP 期间的符号错误

java - 每个 JVM 或每个 CPU 核心的线程数

java - 为什么 JSR/RET 不推荐使用 Java 字节码?

java - 我可以使用 Byte Buddy 重新定义私有(private)方法吗?

java - 已将 Weblogic 证书添加到本地 JDK cacerts。如何在 PCF 中添加证书,以便我可以通过 mulesoft 成功连接到 Weblogic Jms

java - 整数数组还是单个整数?

java - 带有外部 jar dao 的 spring mybatis

java - 随机测试用例失败 - Forked JVM 异常退出。

java - 是否有可能追踪到哪个表达式导致了 NPE?