I have two example class files, one from an example Java app and one from an example C app (compiled to bytecode using LLJVM).
Looking at their outputs, I can see through javap -c -p that for initializing the (static) fields, the Java app shows the following block:
static {};
Code:
0: sipush 1339
3: putstatic #7 //Field SRV_ID
etc
Which is basically the <clinit>
method, if I understand. Or detected as such by a VM I am using.
The C-app however has this:
public {};
Code:
0: sipush 1339
3: putstatic #7 //Field SRV_ID
etc
What is this? My VM does not detect it.
Sample class files. THe first one is from a Java App that prints a message and waits 20s, repeat. The second is a C app that does roughly the same.
http://www.fast-files.com/getfile.aspx?file=156962
http://www.fast-files.com/getfile.aspx?file=156961
Apologies for doing it this way - I do not immediately know how to attach files or efficiently show .class files.
This seems to be a nonstandard declaration that javap
did not consider. Normally, static
initializers are compiled to bytecode methods named <clinit>
having a static
modifier. Apparently, javap
decodes them by just printing the human readable form of the modifier and omitting the <clinit>
name.
Here, it encountered a method named <clinit>
and having the public
modifier (no static
modifier) and just did the same as usual, printing the modifier and omitting the <clinit>
name.
The code generated by LLJVM seems to rely on an old oddity:
In a
class
file whose version number is 51.0 or above, the method must additionally have itsACC_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 itsACC_STATIC
flag.
To me, it was truly surprising to read that in previous versions, the ACC_STATIC
modifier was not mandated and I don’t see any reason to ever exploit that oddity. It seems very natural that a class initializer (that is declared static {}
in Java) should have the ACC_STATIC
flag and I can’t even imagine the supposed semantics of an omitted ACC_STATIC
flag. It means that one of two odd things should happen, a) it is invoked without an instance despite not have the ACC_STATIC
flag (being invoked as-if having it) or b) it is invoked with an instance that must have been created “magically”.
The specification says the following about any non-standard <clinit>
method:
Other methods named
<clinit>
in aclass
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With