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.