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"));
+  }
+}

Reply via email to