我有两个示例类文件,一个来自示例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>
方法说以下内容: