This is an automated email from the ASF dual-hosted git repository.
mchades pushed a commit to branch branch-1.3
in repository https://gitbox.apache.org/repos/asf/gravitino.git
The following commit(s) were added to refs/heads/branch-1.3 by this push:
new 3a6a3577f6 [Cherry-pick to branch-1.3] [#11704] fix(core): add
org.apache.gravitino.hive.* prefix to IsolatedClassLoader.isCatalogClass()
(#11705) (#11718)
3a6a3577f6 is described below
commit 3a6a3577f6ade8aec922825cf9f36bc42ba59880
Author: github-actions[bot]
<41898282+github-actions[bot]@users.noreply.github.com>
AuthorDate: Wed Jun 17 22:58:26 2026 +0800
[Cherry-pick to branch-1.3] [#11704] fix(core): add
org.apache.gravitino.hive.* prefix to IsolatedClassLoader.isCatalogClass()
(#11705) (#11718)
**Cherry-pick Information:**
- Original commit: 5abf8de4347defbb8e46e37951d423ffbc4c2398
- Target branch: `branch-1.3`
- Status: ✅ Clean cherry-pick (no conflicts)
Co-authored-by: weijiajun <[email protected]>
Co-authored-by: weijiajun <[email protected]>
---
.../gravitino/utils/IsolatedClassLoader.java | 26 ++++---
.../gravitino/utils/TestIsolatedClassLoader.java | 91 ++++++++++++++++++++++
2 files changed, 107 insertions(+), 10 deletions(-)
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 a7006aca57..18784e41c1 100644
--- a/core/src/main/java/org/apache/gravitino/utils/IsolatedClassLoader.java
+++ b/core/src/main/java/org/apache/gravitino/utils/IsolatedClassLoader.java
@@ -240,16 +240,22 @@ public class IsolatedClassLoader implements Closeable {
* @return true if the class is a catalog class, false otherwise.
*/
private boolean isCatalogClass(String name) {
- return name.startsWith("org.apache.gravitino.catalog")
- && (name.startsWith("org.apache.gravitino.catalog.hive.")
- || name.startsWith("org.apache.gravitino.catalog.lakehouse.")
- || name.startsWith("org.apache.gravitino.catalog.jdbc.")
- || name.startsWith("org.apache.gravitino.catalog.mysql.")
- || name.startsWith("org.apache.gravitino.catalog.postgresql.")
- || name.startsWith("org.apache.gravitino.catalog.doris.")
- || name.startsWith("org.apache.gravitino.catalog.fileset.")
- || name.startsWith("org.apache.gravitino.catalog.model.")
- || name.startsWith("org.apache.gravitino.catalog.kafka."));
+ // org.apache.gravitino.hive.* covers classes moved to the shared
hive-metastore-common
+ // module by the HiveClient refactoring (e.g. HiveExceptionConverter).
Without this prefix
+ // those classes are treated as shared and loaded by the server
classloader; their
+ // compiler-generated synthetic classes (e.g. $1 from switch-on-enum) are
then requested
+ // from the server classloader which cannot find them, causing a permanent
+ // NoClassDefFoundError that is cached by the JVM for the lifetime of the
process.
+ return name.startsWith("org.apache.gravitino.hive.")
+ || name.startsWith("org.apache.gravitino.catalog.hive.")
+ || name.startsWith("org.apache.gravitino.catalog.lakehouse.")
+ || name.startsWith("org.apache.gravitino.catalog.jdbc.")
+ || name.startsWith("org.apache.gravitino.catalog.mysql.")
+ || name.startsWith("org.apache.gravitino.catalog.postgresql.")
+ || name.startsWith("org.apache.gravitino.catalog.doris.")
+ || name.startsWith("org.apache.gravitino.catalog.fileset.")
+ || name.startsWith("org.apache.gravitino.catalog.model.")
+ || name.startsWith("org.apache.gravitino.catalog.kafka.");
}
/**
diff --git
a/core/src/test/java/org/apache/gravitino/utils/TestIsolatedClassLoader.java
b/core/src/test/java/org/apache/gravitino/utils/TestIsolatedClassLoader.java
new file mode 100644
index 0000000000..c2145dad89
--- /dev/null
+++ b/core/src/test/java/org/apache/gravitino/utils/TestIsolatedClassLoader.java
@@ -0,0 +1,91 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.gravitino.utils;
+
+import java.lang.reflect.Method;
+import java.util.Collections;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+public class TestIsolatedClassLoader {
+
+ private IsolatedClassLoader classLoader;
+ private Method isCatalogClassMethod;
+
+ @BeforeEach
+ public void setUp() throws Exception {
+ classLoader =
+ new IsolatedClassLoader(
+ Collections.emptyList(), Collections.emptyList(),
Collections.emptyList());
+ isCatalogClassMethod =
+ IsolatedClassLoader.class.getDeclaredMethod("isCatalogClass",
String.class);
+ isCatalogClassMethod.setAccessible(true);
+ }
+
+ private boolean isCatalogClass(String name) throws Exception {
+ return (boolean) isCatalogClassMethod.invoke(classLoader, name);
+ }
+
+ @Test
+ public void testHivePackageRecognizedAsCatalogClass() throws Exception {
+ // org.apache.gravitino.hive.* was moved from catalog.hive.* by HiveClient
refactoring.
+ // These must be treated as catalog classes so they are loaded by the
IsolatedClassLoader,
+ // not the server classloader. Otherwise their compiler-generated $1
synthetic classes
+ // (from switch-on-enum) fail to load and the JVM permanently caches the
failure.
+ Assertions.assertTrue(
+
isCatalogClass("org.apache.gravitino.hive.client.HiveExceptionConverter"));
+ Assertions.assertTrue(
+
isCatalogClass("org.apache.gravitino.hive.client.HiveExceptionConverter$1"));
+
Assertions.assertTrue(isCatalogClass("org.apache.gravitino.hive.client.HiveClientPool"));
+
Assertions.assertTrue(isCatalogClass("org.apache.gravitino.hive.HiveClientFactory"));
+
Assertions.assertTrue(isCatalogClass("org.apache.gravitino.hive.SomeOtherClass"));
+ }
+
+ @Test
+ public void testCatalogHivePackageRecognizedAsCatalogClass() throws
Exception {
+ Assertions.assertTrue(
+
isCatalogClass("org.apache.gravitino.catalog.hive.HiveCatalogCapability"));
+ Assertions.assertTrue(
+
isCatalogClass("org.apache.gravitino.catalog.hive.HiveCatalogCapability$1"));
+ Assertions.assertTrue(
+
isCatalogClass("org.apache.gravitino.catalog.hive.HiveCatalogOperations"));
+ }
+
+ @Test
+ public void testOtherCatalogPackagesRecognizedAsCatalogClass() throws
Exception {
+ Assertions.assertTrue(
+
isCatalogClass("org.apache.gravitino.catalog.lakehouse.iceberg.IcebergCatalog"));
+
Assertions.assertTrue(isCatalogClass("org.apache.gravitino.catalog.jdbc.JdbcCatalog"));
+
Assertions.assertTrue(isCatalogClass("org.apache.gravitino.catalog.kafka.KafkaCatalog"));
+
Assertions.assertTrue(isCatalogClass("org.apache.gravitino.catalog.fileset.FilesetCatalog"));
+
Assertions.assertTrue(isCatalogClass("org.apache.gravitino.catalog.model.ModelCatalog"));
+ }
+
+ @Test
+ public void testNonCatalogPackagesNotRecognizedAsCatalogClass() throws
Exception {
+ // Server-side / shared classes must NOT be treated as catalog classes.
+
Assertions.assertFalse(isCatalogClass("org.apache.gravitino.connector.BaseCatalog"));
+
Assertions.assertFalse(isCatalogClass("org.apache.gravitino.NameIdentifier"));
+
Assertions.assertFalse(isCatalogClass("org.apache.gravitino.catalog.SomeSharedClass"));
+ Assertions.assertFalse(isCatalogClass("java.lang.String"));
+ Assertions.assertFalse(isCatalogClass("org.slf4j.Logger"));
+ }
+}