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