An undefined behavior w.r.t. <clinit>

Yuting Chen chenyt at cs.sjtu.edu.cn
Sun Jul 12 16:54:10 UTC 2015


Hi, Gilles, thank you for your information. I read jvms again, and
indeed, it says

"
1. A class or interface has at most one class or interface
initialization method and is initialized (§5.5) by invoking that
method. The initialization method of a class or interface has the
special name <clinit>, takes no arguments, and is void (§4.3.3).

2. 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.

3. 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.

4. 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.
"

Wait..., the sentence still reads a little strange, because the method
in my class is "public abstract void <clinit>();" and I still cannot
decide whether it should have any consequence or not, even though it
may not be an initialization method because it does not have an
ACC_STATIC flag. (it seems that the order of the paragraphs should be
changed to 1->3->4->2.)

In any case, the method has an invalid name (because it has a name
<clinit>) or invalid signature (because it does not have an ACC_STATIC
flag). I am afraid that it still should be rejected by HotSpot for
some format error.

For you question, if the class has a version number less than 51, a
format error will be thrown out when it is run on HotSpot and IBMJ9
("Exception in thread "main" java.lang.ClassFormatError: Absent Code
attribute in method that is not native or abstract in class file
M1436188543_V46"). The results are different only when the version
number is greater than 51.

The two classes are attached. Hope that you can get them.

Yuting Chen

On Sun, Jul 12, 2015 at 4:36 AM, Gilles Duboscq <duboscq at ssw.jku.at> wrote:
> Hi Yuting,
>
> I think the behaviour is well defined even if the <clinit> method is not
> ACC_STATIC: in this case if the class version is >= 51.0 then this method is
> *not* the special "class initializer" method and it will not be called
> during class initialization.
>
> To cite jvms: "Other methods named <clinit> in a class file are of no
> consequence. They are not class or interface initialization methods."
> I do not think the JVM should throw any exception because of this.
>
> Your example is interesting for an other reason though. The class file was
> stripped by the mailing list system but from the javap dump it looks like
> your <clinit> method is abstract and has no code.
> If the class file version was < 51.0, i'm not exactly sure what should
> happen.
>
>  Gilles
>
>
> On Fri, Jul 10, 2015 at 11:34 PM Yuting Chen <chenyt.cs.sjtu at gmail.com>
> wrote:
>>
>> >>Reported to jls-jvms-spec-comments, and so far no response.
>> >>Thus I report the problem here again.
>>
>> Hello, I recently feel puzzling about the JVM behaviors when an
>> illegal <clinit> is met. The specification may not be complete in this
>> part.
>>
>> In the specification (jvms-2.9, se8), we have the words: "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."
>>
>> However, the behavior is undefined if the ACC_STATIC flag is not set.
>> Thus when a class without an ACC_STATIC flag may either be accepted or
>> be rejected, depending on the JVM developers. The results can be
>> unpredictable.
>>
>> I checked this by running a class on OpenJDK8-HotSpot and IBM J9, and
>> found different results. The class can be run on HotSpot without
>> triggering any exceptions (i.e., <clinit> is of no consequence).
>> However, IBM J9 can throw out a FormatError (Exception in thread
>> "main" java.lang.ClassFormatError: JVMCFRE074 no Code attribute
>> specified; class=M1436188543, method=<clinit>()V, pc=0). I checked the
>> specification and still could not decide which JVM behaves correctly.
>>
>> (I thought the question again, and believed that it can be better if
>> HotSpot can also report a ClassFormatError.)
>>
>> The class is attached, and the decompiled code is given next:
>>
>> class M1436188543
>>   minor version: 0
>>   major version: 51
>>   flags: ACC_SUPER
>> Constant pool:
>>    #1 = Utf8               java/lang/Object
>>    #2 = Utf8               <clinit>
>>    #3 = Utf8               SourceFile
>>    #4 = Utf8               M1436188543
>>    #5 = Utf8               main
>>    #6 = Class              #4             // M1436188543
>>    #7 = Utf8               Code
>>    #8 = Utf8               ([Ljava/lang/String;)V
>>    #9 = Utf8               ()V
>>   #10 = Utf8               Jasmin
>>   #11 = Class              #1             // java/lang/Object
>> {
>>   public abstract {};
>>     descriptor: ()V
>>     flags: ACC_PUBLIC, ACC_ABSTRACT
>>
>>   public static void main(java.lang.String[]);
>>     descriptor: ([Ljava/lang/String;)V
>>     flags: ACC_PUBLIC, ACC_STATIC
>>     Code:
>>       stack=0, locals=1, args_size=1
>>          0: return
>> }


More information about the hotspot-runtime-dev mailing list