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

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

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

据我了解,基本上是<clinit>方法。或被我正在使用的VM检测到。

但是,C-app具有以下功能:
public {};
Code:
0: sipush 1339
3: putstatic   #7     //Field SRV_ID
etc

这是什么?我的VM无法检测到它。

示例类文件。
第一个是来自Java App的,该App会打印一条消息并等待20秒钟,重复一次。
第二个是一个大致相同的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:

对我来说,读到以前的版本时没有强制使用ACC_STATIC修饰符真是令人惊讶,而且我看不出有任何理由可以利用这种怪异之处。类初始化器(在Java中被声明为static {})应该具有ACC_STATIC标志,这似乎很自然,我什至无法想象省略的ACC_STATIC标志的假定语义。这意味着应该发生以下两种奇怪的情况之一:a)尽管没有ACC_STATIC标志(如果有的话被调用),却在没有实例的情况下调用了它;或b)在必须“神奇地”创建了一个实例的情况下调用了它”。
specification对任何非标准的<clinit>方法说以下内容:

09-11 18:09