Skip to content

Conversation

@graalvmbot
Copy link

@graalvmbot graalvmbot commented Oct 8, 2025

This PR fixes a problem in the translation of exceptions from HotSpot to libgraal that was exposed now that annotation parsing is done in libgraal:

Caused by: java.lang.InternalError: unexpected problem occurred while encoding an exception to translate it from the JVM heap: java.lang.NoClassDefFoundError: Lorg/checkerframework/checker/nullness/compatqual/NullableDecl;
<<cannot call Java to get cause>>                  
	at java.base@25/jdk.internal.vm.VMSupport.decodeAndThrowThrowable(VMSupport.java:131)
	at LibGraalClassLoader//jdk.vm.ci.hotspot.CompilerToVM.lookupType(Native Method)
	at LibGraalClassLoader//jdk.vm.ci.hotspot.CompilerToVM.lookupType(CompilerToVM.java:251)
	at LibGraalClassLoader//jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.lookupTypeInternal(HotSpotJVMCIRuntime.java:892)
	at LibGraalClassLoader//jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.lookupType(HotSpotJVMCIRuntime.java:860)
	at LibGraalClassLoader//jdk.vm.ci.hotspot.HotSpotResolvedJavaType.lookupType(HotSpotResolvedJavaType.java:83)
	at LibGraalClassLoader//jdk.vm.ci.hotspot.HotSpotResolvedObjectTypeImpl.lookupType(HotSpotResolvedObjectTypeImpl.java:1216)
	at LibGraalClassLoader//jdk.vm.ci.meta.UnresolvedJavaType.resolve(UnresolvedJavaType.java:110)
	at LibGraalClassLoader//jdk.graal.compiler.annotation.AnnotationValueParser.parseSig(AnnotationValueParser.java:220)
	at LibGraalClassLoader//jdk.graal.compiler.annotation.AnnotationValueParser.parseAnnotation(AnnotationValueParser.java:100)
	at LibGraalClassLoader//jdk.graal.compiler.annotation.AnnotationValueParser.parseAnnotations(AnnotationValueParser.java:61)
	at LibGraalClassLoader//jdk.graal.compiler.annotation.AnnotationValueSupport.getDeclaredAnnotationValues(AnnotationValueSupport.java:76)

The problem was 2-fold:

  • Exception translation requires calling from the VM into Java to encode the exception. This PR enhances CompilerThreadCanCallJava so that it will translate pending HotSpot -> libgraal exceptions before closing a scope that allows such calls.
  • Decoding the encoded exception uses Class.forName. As of GR-69927, Class.forName is neutered in libgraal. Rather than reviving this support, I opted to replace the use of Class.forName with an explicit list of supported exception types as there are only a few core exceptions that need type-preserving translation in libgraal.

I tested this in Graal with this patch:

diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/CompilationTask.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/CompilationTask.java
index 42758b7c446..2be34eb5cb8 100644
--- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/CompilationTask.java
+++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/CompilationTask.java
@@ -39,6 +39,7 @@ import java.util.ListIterator;

 import org.graalvm.collections.EconomicMap;

+import jdk.graal.compiler.annotation.AnnotationValueSupport;
 import jdk.graal.compiler.api.replacements.SnippetReflectionProvider;
 import jdk.graal.compiler.code.CompilationResult;
 import jdk.graal.compiler.core.CompilationPrinter;
@@ -52,8 +53,8 @@ import jdk.graal.compiler.debug.DebugCloseable;
 import jdk.graal.compiler.debug.DebugContext;
 import jdk.graal.compiler.debug.DebugContext.Builder;
 import jdk.graal.compiler.debug.DebugContext.Description;
-import jdk.graal.compiler.debug.DebugDumpScope;
 import jdk.graal.compiler.debug.DebugDumpHandlersFactory;
+import jdk.graal.compiler.debug.DebugDumpScope;
 import jdk.graal.compiler.debug.GraalError;
 import jdk.graal.compiler.debug.MethodFilter;
 import jdk.graal.compiler.debug.TTY;
@@ -306,6 +307,11 @@ public class CompilationTask implements CompilationWatchDog.EventHandler {
                 graph = compiler.createGraph(method, entryBCI, profileProvider, compilationId, debug.getOptions(), debug);
                 Suites suites = compiler.getSuites(compiler.getGraalRuntime().getHostProviders(), debug.getOptions());
                 adjustSuitesForRecompilation(debug.getOptions(), suites);
+
+                if (method.getDeclaredAnnotationInfo() != null) {
+                    System.out.printf("%s -> %s%n", method.format("%h.%n(%p)"), AnnotationValueSupport.getDeclaredAnnotationValues(method));
+                }
+
                 result = compiler.compile(graph, shouldRetainLocalVariables, shouldUsePreciseUnresolvedDeopts, eagerResolving, compilationId, debug, suites);
                 performRecompilationCheck(debug.getOptions(), method);
             } catch (Throwable e) {

and by running Test.java (in fish shell):

compiler> mx -p ../vm --env libgraal build
compiler> javac -cp (mx classpath JIMFS GUAVA) Test.java
compiler> eval (mx -p ../vm --env libgraal graalvm-home)/bin/java -cp (mx classpath JIMFS GUAVA):. -XX:-TieredCompilation -Xlog:exceptions Test

The output is:

[0.088s][info][exceptions] Exception <a 'java/lang/NoSuchMethodError'{0x0000000ae8535448}: 'java.lang.Object java.lang.invoke.DirectMethodHandle$Holder.invokeStaticInit(java.lang.Object)'> (0x0000000ae8535448)
[                        ] thrown [src/hotspot/share/interpreter/linkResolver.cpp, line 804]
[                        ] for thread 0x0000000103228ca0
[0.133s][info][exceptions] Exception <a 'java/lang/ClassNotFoundException'{0x0000000ae81ebf98}: org.checkerframework.checker.nullness.compatqual.NullableDecl>
[                        ]  thrown in interpreter method <{method} {0x00000f00001cc3c0} 'loadClass' '(Ljava/lang/String;Z)Ljava/lang/Class;' in 'jdk/internal/loader/BuiltinClassLoader'>
[                        ]  at bci 19 for thread 0x00000007a9087200 (JVMCI-native CompilerThread0)
[0.134s][info][exceptions] Exception <a 'java/lang/ClassNotFoundException'{0x0000000ae81ebf98}: org.checkerframework.checker.nullness.compatqual.NullableDecl>
[                        ]  thrown in interpreter method <{method} {0x00000f0000181b00} 'loadClass' '(Ljava/lang/String;)Ljava/lang/Class;' in 'java/lang/ClassLoader'>
[                        ]  at bci 3 for thread 0x00000007a9087200 (JVMCI-native CompilerThread0)
[0.134s][info][exceptions] Exception <a 'java/lang/NoClassDefFoundError'{0x0000000ae81ec2d8}: Lorg/checkerframework/checker/nullness/compatqual/NullableDecl;> (0x0000000ae81ec2d8)
[                        ] thrown [src/hotspot/share/classfile/systemDictionary.cpp, line 316]
[                        ] for thread 0x00000007a9087200
PathType$ParseResult.root() -> declared annotations attribute parsed to empty map
[0.163s][info][exceptions] Exception <a 'java/lang/ClassNotFoundException'{0x0000000ae81f0890}: javax.annotation.CheckForNull>
[                        ]  thrown in interpreter method <{method} {0x00000f00001cc3c0} 'loadClass' '(Ljava/lang/String;Z)Ljava/lang/Class;' in 'jdk/internal/loader/BuiltinClassLoader'>
[                        ]  at bci 19 for thread 0x00000007a9087200 (JVMCI-native CompilerThread0)
[0.163s][info][exceptions] Exception <a 'java/lang/ClassNotFoundException'{0x0000000ae81f0890}: javax.annotation.CheckForNull>
[                        ]  thrown in interpreter method <{method} {0x00000f0000181b00} 'loadClass' '(Ljava/lang/String;)Ljava/lang/Class;' in 'java/lang/ClassLoader'>
[                        ]  at bci 3 for thread 0x00000007a9087200 (JVMCI-native CompilerThread0)
[0.163s][info][exceptions] Exception <a 'java/lang/NoClassDefFoundError'{0x0000000ae81f0bb0}: Ljavax/annotation/CheckForNull;> (0x0000000ae81f0bb0)
[                        ] thrown [src/hotspot/share/classfile/systemDictionary.cpp, line 316]
[                        ] for thread 0x00000007a9087200
Splitter$SplittingIterator.computeNext() -> declared annotations attribute parsed to empty map

@graalvmbot graalvmbot merged commit e58d830 into jdk25 Oct 10, 2025
108 checks passed
@graalvmbot graalvmbot deleted the ds/GR-70612 branch October 10, 2025 06:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants