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

Yuting Chen chenyt.cs.sjtu at gmail.com
Thu Apr 13 23:15:05 UTC 2017


Thanks, Remi and Michael.

The difference appears only when all of the paths end in athrow. Then
what does the comment ("Return TRUE if all code paths starting with
start_bc_offset end in bytecode athrow or loop") in verifier.cpp mean?
It seems that J9 follows this comment.

Both verifiers can decline the class if "athrow" is changed to "return".

On Thu, Apr 13, 2017 at 3:54 PM, Michael Rasmussen
<michael.rasmussen at zeroturnaround.com> wrote:
> 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