This is an automated email from the ASF dual-hosted git repository.

yuqi1129 pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/gravitino.git


The following commit(s) were added to refs/heads/main by this push:
     new 4ff7aac259 [#12014] fix(core): Don't wrap plain ClassNotFoundException 
in IsolatedClassLoader (#12015)
4ff7aac259 is described below

commit 4ff7aac2590b2285df4ac19ccb47e75ed6098089
Author: jarred0214 <[email protected]>
AuthorDate: Thu Jul 16 11:52:04 2026 +0800

    [#12014] fix(core): Don't wrap plain ClassNotFoundException in 
IsolatedClassLoader (#12015)
    
    ### What changes were proposed in this pull request?
    
    This PR updates `IsolatedClassLoader.CustomURLClassLoader#loadClass` to
    rethrow a
    `ClassNotFoundException` from `doLoadClass` as-is, instead of wrapping
    it in a new
    `ClassNotFoundException` with a cause. Other exceptions are still
    wrapped as before.
    
    It also adds a unit test verifying that a class-miss surfaces as a plain
    `ClassNotFoundException` with a `null` cause.
    
    ### Why are the changes needed?
    
    Probe-driven callers such as Janino (used by codegen paths, e.g. Paimon)
    try a series of
    candidate class names (`Override`, then `java.lang.Override`, ...) and
    rely on the standard
    classloader contract: a `ClassNotFoundException` with a `null` cause
    means "class does not
    exist, try the next candidate", while a non-null cause means a fatal
    loading failure.
    
    `IsolatedClassLoader` previously wrapped every miss in a
    `ClassNotFoundException` with a
    cause, which turned an ordinary probe miss into a fatal failure and
    broke such codegen
    paths under the isolated catalog classloader.
    
    Note: the classloader does not (and should not) resolve simple names
    like `Override` to
    `java.lang.Override` itself; with this fix, probing callers can handle
    that themselves.
    
    Fix: #12014
    
    ### Does this PR introduce _any_ user-facing change?
    
    No.
    
    ### How was this patch tested?
    
    Added `testClassNotFoundExceptionDoesNotWrapProbeMiss` in
    `TestIsolatedClassLoader`,
    which fails against the old wrapping behavior and passes with this
    change.
    
    ---------
    
    Co-authored-by: jarred0214 <[email protected]>
---
 .../java/org/apache/gravitino/utils/IsolatedClassLoader.java |  7 ++++++-
 .../org/apache/gravitino/utils/TestIsolatedClassLoader.java  | 12 ++++++++++++
 2 files changed, 18 insertions(+), 1 deletion(-)

diff --git 
a/core/src/main/java/org/apache/gravitino/utils/IsolatedClassLoader.java 
b/core/src/main/java/org/apache/gravitino/utils/IsolatedClassLoader.java
index 18784e41c1..6c80a6caba 100644
--- a/core/src/main/java/org/apache/gravitino/utils/IsolatedClassLoader.java
+++ b/core/src/main/java/org/apache/gravitino/utils/IsolatedClassLoader.java
@@ -172,8 +172,13 @@ public class IsolatedClassLoader implements Closeable {
 
       try {
         return clazz == null ? doLoadClass(name, resolve) : clazz;
+      } catch (ClassNotFoundException e) {
+        // Probe-driven callers, such as Janino, use a plain 
ClassNotFoundException as a
+        // signal that the current candidate name missed and they should try 
the next one.
+        // Wrapping it with a cause changes that signal into a fatal loading 
failure.
+        throw e;
       } catch (Exception e) {
-        throw new ClassNotFoundException("Class not found " + name, e);
+        throw new ClassNotFoundException("Failed to load " + name, e);
       }
     }
 
diff --git 
a/core/src/test/java/org/apache/gravitino/utils/TestIsolatedClassLoader.java 
b/core/src/test/java/org/apache/gravitino/utils/TestIsolatedClassLoader.java
index c2145dad89..7dc55b1343 100644
--- a/core/src/test/java/org/apache/gravitino/utils/TestIsolatedClassLoader.java
+++ b/core/src/test/java/org/apache/gravitino/utils/TestIsolatedClassLoader.java
@@ -44,6 +44,18 @@ public class TestIsolatedClassLoader {
     return (boolean) isCatalogClassMethod.invoke(classLoader, name);
   }
 
+  @Test
+  public void testClassNotFoundExceptionDoesNotWrapProbeMiss() {
+    // Probe-driven callers such as Janino expect a plain 
ClassNotFoundException for misses
+    // so they can continue trying the next candidate name.
+    ClassNotFoundException exception =
+        Assertions.assertThrows(
+            ClassNotFoundException.class,
+            () -> classLoader.withClassLoader(cl -> 
cl.loadClass("UnknownProbeClass")));
+
+    Assertions.assertNull(exception.getCause());
+  }
+
   @Test
   public void testHivePackageRecognizedAsCatalogClass() throws Exception {
     // org.apache.gravitino.hive.* was moved from catalog.hive.* by HiveClient 
refactoring.

Reply via email to