HotSpot and IBM's J9 behave a little different when verifying this class

Michael Rasmussen michael.rasmussen at zeroturnaround.com
Thu Apr 13 22:54:50 UTC 2017


Your problem is, that the stackmap frame in your else has top as local
0, instead of an uninitializedThis, meaning else-block doesn't have
flagThisUninit  in the flags, so it shouldn't verify.

This was changed in 8u121, to conform with the Maintenance Releases of
JSRs 336/337 done in 2015.
Prior to that, flags was not compared when checking if stackmap frames
were compatible, apparently J9 hasn't updated to follow this yet.

Also see: http://mail.openjdk.java.net/pipermail/hotspot-dev/2017-January/025781.html

/Michael

On 14 April 2017 at 01:39, Remi Forax <forax at univ-mlv.fr> wrote:
> Disclaimer, i'm not an hotspot guy.
>
> J9 seems wrong, to me.
>
> If you just take a look to the code,
> you have a path to go out of the constructor without having 'this' fully initialized,
> so whatever the VM impelemntations say, this code is not a valid one.
>
> Now, Hotspot refuses to merge a path where this is initialized with a path where this is not initialized because it will forget that there is a path where this is not initialized,
> it seems to be the right thing to do.
>
> cheers,
> Rémi
>
> ----- Mail original -----
>> De: "Yuting Chen" <chenyt.cs.sjtu at gmail.com>
>> À: hotspot-dev at openjdk.java.net
>> Envoyé: Vendredi 14 Avril 2017 00:02:42
>> Objet: Fwd: HotSpot and IBM's J9 behave a little different when verifying this class
>
>> Re-post my previous example.
>>
>> I recently found an interesting class. Hope that I can get answers here.
>>
>> The bytecode is shown as follows. Hotspot can catch some
>> inconsistencies here (Reason: Current frame's flags are not assignable
>> to stack map frame's), while J9 cannot.
>>
>> I thought J9 was wrong until I went into HotSpot's source code and saw
>> some comments in share/vm/classfile/verifier.cpp.  It says that the
>> verifier "Return TRUE if all code paths starting with start_bc_offset
>> end in bytecode athrow or loop" (a comment before bool
>> ClassVerifier::ends_in_athrow(u4 start_bc_offset)). Clearly the paths
>> in Vector1(int, int) end in athrow, and the verifier fails.
>>
>> Can anyone explain the reason why the class still cannot pass the
>> verification, and which verifier needs to be fixed.
>>
>> ****************
>>
>> public class Vector1 extends java.util.AbstractList
>>  minor version: 0
>>  major version: 52
>>  flags: ACC_PUBLIC, ACC_SUPER
>> Constant pool:
>>   #1 = Utf8               Vector1
>>   #2 = Class              #1             // Vector1
>>   #3 = Utf8               java/util/AbstractList
>>   #4 = Class              #3             // java/util/AbstractList
>>   #5 = Utf8               <init>
>>   #6 = Utf8               (II)V
>>   #7 = Utf8               ()V
>>   #8 = NameAndType        #5:#7          // "<init>":()V
>>   #9 = Methodref          #4.#8          // java/util/AbstractList."<init>":()V
>>  #10 = Utf8               java/lang/Exception
>>  #11 = Class              #10            // java/lang/Exception
>>  #12 = Methodref          #11.#8         // java/lang/Exception."<init>":()V
>>  #13 = Utf8               main
>>  #14 = Utf8               ([Ljava/lang/String;)V
>>  #15 = NameAndType        #5:#6          // "<init>":(II)V
>>  #16 = Methodref          #2.#15         // Vector1."<init>":(II)V
>>  #17 = Utf8               Code
>>  #18 = Utf8               StackMapTable
>> {
>>  public Vector1(int, int);
>>    descriptor: (II)V
>>    flags: ACC_PUBLIC
>>    Code:
>>      stack=2, locals=3, args_size=3
>>         0: iload_1
>>         1: iflt          11
>>         4: aload_0
>>         5: invokespecial #9                  // Method
>> java/util/AbstractList."<init>":()V
>>         8: goto          11
>>        11: new           #11                 // class java/lang/Exception
>>        14: dup
>>        15: invokespecial #12                 // Method
>> java/lang/Exception."<init>":()V
>>        18: athrow
>>      StackMapTable: number_of_entries = 1
>>        frame_type = 255 /* full_frame */
>>          offset_delta = 11
>>          locals = [ top, int, int ]
>>          stack = []
>>
>>  public static void main(java.lang.String[]);
>>    descriptor: ([Ljava/lang/String;)V
>>    flags: ACC_PUBLIC, ACC_STATIC
>>    Code:
>>      stack=3, locals=1, args_size=1
>>         0: new           #2                  // class Vector1
>>         3: bipush        10
>>         5: iconst_0
>>         6: invokespecial #16                 // Method "<init>":(II)V
>>         9: return
>> }
>>
>> HotSpot reports the next verifyerror, while J9 does not:
>> Exception in thread "main" java.lang.VerifyError: Inconsistent
>> stackmap frames at branch target 11
>> Exception Details:
>>  Location:
>>    Vector1.<init>(II)V @11: new
>>  Reason:
>>    Current frame's flags are not assignable to stack map frame's.
>>  Current Frame:
>>    bci: @1
>>    flags: { flagThisUninit }
>>    locals: { uninitializedThis, integer, integer }
>>    stack: { integer }
>>  Stackmap Frame:
>>    bci: @11
>>    flags: { }
>>    locals: { top, integer, integer }
>>    stack: { }
>>  Bytecode:
>>    0000000: 1b9b 000a 2ab7 0009 a700 03bb 000b 59b7
>>    0000010: 000c bf
>>  Stackmap Table:
>>     full_frame(@11,{Top,Integer,Integer},{})


More information about the hotspot-dev mailing list