Two verification missings

David Holmes david.holmes at oracle.com
Thu Jun 25 04:18:35 UTC 2015


On 25/06/2015 8:22 AM, Yuting Chen wrote:
> Can anyone help me check whether some errors should be reported by
> Hotspots?  The two classes are also attached.
>
> I generated some Java classes from SOOT's Jimple's code. When I re-checked
> the code, I noticed that two classes are absolutely not correct. I'd expect
> that some errors (e.g., VerifyError) could be thrown during the operations
> of the JVMs, but they are not. Can anyone tell me the reasons?
>
> Case 1: A VerifyError is caught by GCJ-Java, but missed by Hotspot.
> However, the type-casting between java.lang.String and java.util.Map may be
> unsafe. Verification results: (a) Hotspot 7/8/9: OK; (b) GCJ-Java JVM
> (1.5.0): Exception in ... Caused by: java.lang.VerifyError: verification
> failed at PC 1 in M1433982529S:internalTransform((Ljava.lang.String;)V):
> incompatible type on stack ...

Can't comment on this part.

> The Jimple's code.
> public class M1433982529S extends java.lang.Object
> {
>      protected void internalTransform(java.lang.String)
>      {
>          java.util.Map r0;
>
>          r0 := @parameter0: java.util.Map;
>          staticinvoke <java.lang.Object: boolean
> getBoolean(java.util.Map)>(r0);
>
>          return;
>      }
> }
>
> Decompile the class: javap -verbose M1433982529S
> public class M1433982529S
>    minor version: 0
>    major version: 46
>    flags: ACC_PUBLIC, ACC_SUPER
> Constant pool:
>     #1 = Utf8               java/lang/Object
>     #2 = Utf8               SourceFile
>     #3 = Utf8               main
>     #4 = Methodref          #15.#13        //
> java/lang/Object.getBoolean:(Ljava/util/Map;)Z
>     #5 = Utf8               Code
>     #6 = Class              #12            // M1433982529S
>     #7 = Utf8               getBoolean
>     #8 = Utf8               ([Ljava/lang/String;)V
>     #9 = Utf8               Jasmin
>    #10 = Utf8               internalTransform
>    #11 = Utf8               (Ljava/util/Map;)Z
>    #12 = Utf8               M1433982529S
>    #13 = NameAndType        #7:#11         // getBoolean:(Ljava/util/Map;)Z
>    #14 = Utf8               (Ljava/lang/String;)V
>    #15 = Class              #1             // java/lang/Object
> {
>    ...
>    protected void internalTransform(java.lang.String);
>      descriptor: (Ljava/lang/String;)V
>      flags: ACC_PROTECTED
>      Code:
>        stack=1, locals=2, args_size=2
>           0: aload_1
>           1: invokestatic  #4                  // Method
> java/lang/Object.getBoolean:(Ljava/util/Map;)Z
>           4: pop
>           5: return
> }
>
> Case 2: Hotspot may miss some checking for classes with low version
> numbers. I generated two classes for the next Jimple's code: one is with
> version 46, and another with version 51 (they are different only in their
> version numbers). I ran the two classes on Hotspot9, and one (46) was
> accepted and another (51) was rejected (with verifyError). In addition,

For backward compatibility reasons in some/many cases if the verifier 
was doing something incorrect, or if the specification was clarified or 
modified, then the new rules would only be applied to the latest version 
of the classfile (and future versions of course). So you can find a 
number of dubious/illegal constructs in say a version 49 class that are 
rejected if they appear in say a version 50+ class.

David

> when I ran the two classes on GCJ-Java JVMs, both are rejected with
> VerifyErrors (...verification failed at PC 6 in
> M1433584778S:encodeObject(()V): merging initialized and uninitialized
> types...).
>
> public class M1433584778S extends java.lang.Object
> {
>      private void <init>()
>      {
>          M1433584778S r0;
>
>          r0 := @this: M1433584778S;
>          specialinvoke r0.<java.lang.Object: void <init>()>();
>          return;
>      }
>
>      public static void encodeObject()
>      {
>          java.lang.String r1, r2;
>          java.lang.Throwable r3;
>
>       label0:
>          r1 = new java.lang.String;
>
>       label1:
>          return;
>
>       label2:
>          r3 := @caughtexception;
>          goto label1;
>
>          catch java.lang.RuntimeException from label0 to label1 with label2;
>
>      }
> }
>
> Decompile the classes and found that:
> public class M1433584778S
>    minor version: 0
>    major version: 46
>    flags: ACC_PUBLIC, ACC_SUPER
> Constant pool:
>     #1 = Utf8               ([Ljava/lang/String;)V
>     #2 = Utf8               java/lang/Object
>     #3 = Utf8               <init>
>     #4 = Class              #2             // java/lang/Object
>     #5 = NameAndType        #3:#7          // "<init>":()V
>     #6 = Class              #14            // java/lang/String
>     #7 = Utf8               ()V
>     #8 = Utf8               M1433584778S
>     #9 = Utf8               Code
>    #10 = Utf8               main
>    #11 = Utf8               SourceFile
>    #12 = Class              #8             // M1433584778S
>    #13 = Class              #15            // java/lang/RuntimeException
>    #14 = Utf8               java/lang/String
>    #15 = Utf8               java/lang/RuntimeException
>    #16 = Utf8               Jasmin
>    #17 = Methodref          #4.#5          // java/lang/Object."<init>":()V
>    #18 = Utf8               encodeObject
> {
>    ...
>    public static void encodeObject();
>      descriptor: ()V
>      flags: ACC_PUBLIC, ACC_STATIC
>      Code:
>        stack=1, locals=1, args_size=0
>           0: new           #6                  // class java/lang/String
>           3: astore_0
>           4: return
>           5: astore_0
>           6: goto          4
>        Exception table:
>           from    to  target type
>               0     4     5   Class java/lang/RuntimeException
> }
>


More information about the hotspot-runtime-dev mailing list