A class is accessable from another?

Ioi Lam ioi.lam at oracle.com
Sun Jan 3 08:11:27 UTC 2016


The two exceptions that you see here are related to the internal 
implementation of the OpenJDK:

Case 1: For JDK 7/8, the exception happened here:

Exception in thread "main" java.lang.IllegalAccessError: tried to access 
class java.lang.AbstractStringBuilder from class M1450648087
     at java.lang.Class.getDeclaredMethods0(Native Method)
     at java.lang.Class.privateGetDeclaredMethods(Class.java:2688)
     at java.lang.Class.getMethod0(Class.java:2937)
     at java.lang.Class.getMethod(Class.java:1771)
     at 
sun.launcher.LauncherHelper.validateMainClass(LauncherHelper.java:544)
     at 
sun.launcher.LauncherHelper.checkAndLoadMain(LauncherHelper.java:526)

Note that java.lang.AbstractStringBuilder is an internal, non-public 
class and it's inaccessible by class M1450648087.

This exception happens only when the Java launcher looks up the "main" 
method. If you put the "throws AbstractStringBuilder" in any other 
methods, the JVM will not complain (see 
https://docs.oracle.com/javase/specs/jvms/se8/jvms8.pdf, 4.7.5 The 
Exceptions Attribute). So it's quite plausible that the J9 launcher does 
something different than the sun.launcher and avoids the exception.

Case 2: In JDK8, the internal class GraphicsPrimitive$TraceReporter was 
a subclass of Thread. In JDK9, this class has been changed to "implement 
Runnable". Hence it's no longer assignable to Thread. You can read more 
about the Verifier in the JVM Spec link posted above.


In both cases, your code is accessing an internal JDK class, so the 
behavior may change in different JDK releases, even if there are no spec 
changes.


Thanks
- Ioi


On 1/1/16 4:22 AM, 陈雨亭 wrote:
> Hello, everyone. I created a class M1450648087 using soot, while the 
> class is
> executable on some JVMs but not on HotSpot releases:
> (1) When the class is tested on IBM's J9 or GIJ, it is executable 
> (i.e., "Executed!"
> is printed out);
> (2) When the class is tested using OpenJDK for Java7/8, it says
> "java.lang.IllegalAccessError: tried to access class 
> java.lang.AbstractStringBuilder
> from class M1450648087"  (the run() method throws 
> java.lang.AbstractStringBuilder );
> (3) When the class is tested using OpenJDK for Java9, it says 
> "java.lang.VerifyError:
> Bad type on operand stack ...Type 
> 'sun/java2d/loops/GraphicsPrimitive$TraceReporter'
> (current frame, stack[1]) is not assignable to 'java/lang/Thread' ".
> (caused by run()...17: invokevirtual #10 // Method 
> java/lang/Runtime.addShutdownHook:(Ljava/lang/Thread;)V)
>
> My problem is:
> (1) Where can I find any reference about whether one class is accessable
> from another? Why is the class java.lang.AbstractStringBuilder 
> accessable from
> M1450648087 when running on J9 but not accessable
> when on HotSpot releases?
>
> (2) When can one class be assignable to another? I cannot find any
> materials about this. I guess HotSpot for Java9 rejects the assignment
> by taking some new rules. Where can I find these rules?
>
> Yuting
> ************************************************************************************************************* 
>
> The decompiled code is given as follows.
>
> javap -verbose M1450648087.class
> class M1450648087
>  minor version: 0
>  major version: 51
>  flags: ACC_SUPER
> Constant pool:
>   #1 = Utf8               Executed!
>   #2 = Utf8               ()V
>   #3 = Utf8               main
>   #4 = String             #1             // Executed!
>   #5 = Utf8               java/lang/Object
>   #6 = Utf8               java/lang/AbstractStringBuilder
>   #7 = Class              #5             // java/lang/Object
>   #8 = Methodref          #24.#35        // 
> java/io/PrintStream.println:(Ljava/lang/String;)V
>   #9 = Utf8               ()Ljava/lang/Runtime;
>  #10 = Methodref          #45.#11        // 
> java/lang/Runtime.addShutdownHook:(Ljava/lang/Thread;)V
>  #11 = NameAndType        #47:#26        // 
> addShutdownHook:(Ljava/lang/Thread;)V
>  #12 = Utf8               java/lang/System
>  #13 = Class              #6             // 
> java/lang/AbstractStringBuilder
>  #14 = Class              #12            // java/lang/System
>  #15 = Utf8               ()Ljava/lang/Object;
>  #16 = Utf8               M1450648087
>  #17 = Utf8 sun/java2d/loops/GraphicsPrimitive$TraceReporter
>  #18 = Methodref          #41.#29        // 
> sun/java2d/loops/GraphicsPrimitive$TraceReporter.setContextClassLoader:(Ljava/lang/ClassLoader;)V
>  #19 = Utf8               run
>  #20 = Methodref          #41.#23        // 
> sun/java2d/loops/GraphicsPrimitive$TraceReporter."<init>":()V
>  #21 = Utf8               ([Ljava/lang/String;)V
>  #22 = Class              #16            // M1450648087
>  #23 = NameAndType        #30:#2         // "<init>":()V
>  #24 = Class              #44            // java/io/PrintStream
>  #25 = Utf8               Exceptions
>  #26 = Utf8               (Ljava/lang/Thread;)V
>  #27 = Utf8               SourceFile
>  #28 = Utf8               println
>  #29 = NameAndType        #48:#49        // 
> setContextClassLoader:(Ljava/lang/ClassLoader;)V
>  #30 = Utf8               <init>
>  #31 = NameAndType        #32:#46        // out:Ljava/io/PrintStream;
>  #32 = Utf8               out
>  #33 = NameAndType        #38:#9         // 
> getRuntime:()Ljava/lang/Runtime;
>  #34 = Methodref          #7.#23         // java/lang/Object."<init>":()V
>  #35 = NameAndType        #28:#42        // println:(Ljava/lang/String;)V
>  #36 = Methodref          #45.#33        // 
> java/lang/Runtime.getRuntime:()Ljava/lang/Runtime;
>  #37 = Utf8               Jasmin
>  #38 = Utf8               getRuntime
>  #39 = Utf8               java/lang/Runtime
>  #40 = Fieldref           #14.#31        // 
> java/lang/System.out:Ljava/io/PrintStream;
>  #41 = Class              #17            // 
> sun/java2d/loops/GraphicsPrimitive$TraceReporter
>  #42 = Utf8               (Ljava/lang/String;)V
>  #43 = Utf8               Code
>  #44 = Utf8               java/io/PrintStream
>  #45 = Class              #39            // java/lang/Runtime
>  #46 = Utf8               Ljava/io/PrintStream;
>  #47 = Utf8               addShutdownHook
>  #48 = Utf8               setContextClassLoader
>  #49 = Utf8               (Ljava/lang/ClassLoader;)V
> {
>  M1450648087();
>    descriptor: ()V
>    flags:
>    Code:
>      stack=1, locals=1, args_size=1
>         0: aload_0
>         1: invokespecial #34                 // Method 
> java/lang/Object."<init>":()V
>         4: return
>
>  public java.lang.Object run() throws java.lang.AbstractStringBuilder;
>    descriptor: ()Ljava/lang/Object;
>    flags: ACC_PUBLIC
>    Code:
>      stack=2, locals=1, args_size=1
>         0: new           #41                 // class 
> sun/java2d/loops/GraphicsPrimitive$TraceReporter
>         3: dup
>         4: invokespecial #20                 // Method 
> sun/java2d/loops/GraphicsPrimitive$TraceReporter."<init>":()V
>         7: astore_0
>         8: aload_0
>         9: aconst_null
>        10: invokevirtual #18                 // Method 
> sun/java2d/loops/GraphicsPrimitive$TraceReporter.setContextClassLoader:(Ljava/lang/ClassLoader;)V
>        13: invokestatic  #36                 // Method 
> java/lang/Runtime.getRuntime:()Ljava/lang/Runtime;
>        16: aload_0
>        17: invokevirtual #10                 // Method 
> java/lang/Runtime.addShutdownHook:(Ljava/lang/Thread;)V
>        20: aconst_null
>        21: areturn
>    Exceptions:
>      throws java.lang.AbstractStringBuilder
>
>  public static void main(java.lang.String[]);
>    descriptor: ([Ljava/lang/String;)V
>    flags: ACC_PUBLIC, ACC_STATIC
>    Code:
>      stack=2, locals=1, args_size=1
>         0: getstatic     #40                 // Field 
> java/lang/System.out:Ljava/io/PrintStream;
>         3: ldc           #4                  // String Executed!
>         5: invokevirtual #8                  // Method 
> java/io/PrintStream.println:(Ljava/lang/String;)V
>         8: return
> }



More information about the hotspot-runtime-dev mailing list