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

wgtmac pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/parquet-java.git


The following commit(s) were added to refs/heads/master by this push:
     new d676501a5 GH-3644: Handle NoClassDefFoundError in DynMethods (#3645)
d676501a5 is described below

commit d676501a58472cb03b5184fb53223a37be92b18a
Author: Eduard Tudenhoefner <[email protected]>
AuthorDate: Tue Jul 14 11:05:22 2026 +0200

    GH-3644: Handle NoClassDefFoundError in DynMethods (#3645)
---
 .../java/org/apache/parquet/util/DynMethods.java   |  4 +-
 .../apache/parquet/util/TestDynConstructors.java   | 62 ++++++++++++++++++++
 .../org/apache/parquet/util/TestDynMethods.java    | 68 ++++++++++++++++++++++
 3 files changed, 132 insertions(+), 2 deletions(-)

diff --git 
a/parquet-common/src/main/java/org/apache/parquet/util/DynMethods.java 
b/parquet-common/src/main/java/org/apache/parquet/util/DynMethods.java
index 082f058e6..0d0728329 100644
--- a/parquet-common/src/main/java/org/apache/parquet/util/DynMethods.java
+++ b/parquet-common/src/main/java/org/apache/parquet/util/DynMethods.java
@@ -243,7 +243,7 @@ public class DynMethods {
       try {
         Class<?> targetClass = Class.forName(className, true, loader);
         impl(targetClass, methodName, argClasses);
-      } catch (ClassNotFoundException e) {
+      } catch (ClassNotFoundException | NoClassDefFoundError e) {
         // class not found on supplied classloader.
         LOG.debug("failed to load class {}", className, e);
       }
@@ -352,7 +352,7 @@ public class DynMethods {
       try {
         Class<?> targetClass = Class.forName(className, true, loader);
         hiddenImpl(targetClass, methodName, argClasses);
-      } catch (ClassNotFoundException e) {
+      } catch (ClassNotFoundException | NoClassDefFoundError e) {
         // class not found on supplied classloader.
         LOG.debug("failed to load class {}", className, e);
       }
diff --git 
a/parquet-common/src/test/java/org/apache/parquet/util/TestDynConstructors.java 
b/parquet-common/src/test/java/org/apache/parquet/util/TestDynConstructors.java
index 26124b9c8..9327660f8 100644
--- 
a/parquet-common/src/test/java/org/apache/parquet/util/TestDynConstructors.java
+++ 
b/parquet-common/src/test/java/org/apache/parquet/util/TestDynConstructors.java
@@ -19,6 +19,9 @@
 
 package org.apache.parquet.util;
 
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+
 import java.util.concurrent.Callable;
 import org.apache.parquet.TestUtils;
 import org.apache.parquet.util.Concatenator.SomeCheckedException;
@@ -166,4 +169,63 @@ public class TestDynConstructors {
     Assert.assertNotNull("Should allow invokeChecked(null, ...)", 
ctor.invokeChecked(null));
     Assert.assertNotNull("Should allow invoke(null, ...)", ctor.invoke(null));
   }
+
+  @Test
+  public void implWithNoClassDefFoundError() throws Exception {
+    ClassLoader errorLoader = new 
ClassLoader(Thread.currentThread().getContextClassLoader()) {
+      @Override
+      public Class<?> loadClass(String name, boolean resolve) throws 
ClassNotFoundException {
+        if ("org.apache.parquet.MissingDependencyClass".equals(name)) {
+          throw new NoClassDefFoundError("some/TransitiveDependency");
+        }
+
+        return super.loadClass(name, resolve);
+      }
+    };
+
+    assertThatThrownBy(() -> new DynConstructors.Builder(MyInterface.class)
+            .loader(errorLoader)
+            .impl("org.apache.parquet.MissingDependencyClass")
+            .buildChecked())
+        .isInstanceOf(NoSuchMethodException.class)
+        .hasMessageStartingWith("Cannot find constructor for interface")
+        .hasMessageContaining("Missing 
org.apache.parquet.MissingDependencyClass");
+
+    assertThat(new DynConstructors.Builder(MyInterface.class)
+            .loader(errorLoader)
+            .impl("org.apache.parquet.MissingDependencyClass")
+            .impl(MyClass.class)
+            .buildChecked()
+            .newInstance())
+        .isInstanceOf(MyClass.class);
+
+    assertThat(new DynConstructors.Builder(MyInterface.class)
+            .loader(errorLoader)
+            .hiddenImpl("org.apache.parquet.MissingDependencyClass")
+            .impl(MyClass.class)
+            .buildChecked()
+            .newInstance())
+        .isInstanceOf(MyClass.class);
+  }
+
+  @Test
+  public void implWithExceptionInInitializerError() {
+    ClassLoader errorLoader = new 
ClassLoader(Thread.currentThread().getContextClassLoader()) {
+      @Override
+      public Class<?> loadClass(String name, boolean resolve) {
+        throw new ExceptionInInitializerError("static initializer failed");
+      }
+    };
+
+    assertThatThrownBy(() -> new DynConstructors.Builder(MyInterface.class)
+            .loader(errorLoader)
+            .impl("org.apache.parquet.FailingInitClass")
+            .buildChecked())
+        .isInstanceOf(ExceptionInInitializerError.class)
+        .hasMessage("static initializer failed");
+  }
+
+  public interface MyInterface {}
+
+  public static class MyClass implements MyInterface {}
 }
diff --git 
a/parquet-common/src/test/java/org/apache/parquet/util/TestDynMethods.java 
b/parquet-common/src/test/java/org/apache/parquet/util/TestDynMethods.java
index 94e9ed93a..59c6d3716 100644
--- a/parquet-common/src/test/java/org/apache/parquet/util/TestDynMethods.java
+++ b/parquet-common/src/test/java/org/apache/parquet/util/TestDynMethods.java
@@ -19,6 +19,9 @@
 
 package org.apache.parquet.util;
 
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+
 import java.util.concurrent.Callable;
 import org.apache.parquet.TestUtils;
 import org.apache.parquet.util.Concatenator.SomeCheckedException;
@@ -306,4 +309,69 @@ public class TestDynMethods {
     Assert.assertNull("NOOP can be bound to null", 
noop.bind(null).invoke("a"));
     Assert.assertNull("NOOP can be static", noop.asStatic().invoke("a"));
   }
+
+  static class Available {
+    public static String register() {
+      return "available";
+    }
+
+    @SuppressWarnings("unused")
+    private static String hiddenRegister() {
+      return "hidden-available";
+    }
+  }
+
+  @Test
+  public void implWithNoClassDefFoundError() throws NoSuchMethodException {
+    ClassLoader errorLoader = new 
ClassLoader(Thread.currentThread().getContextClassLoader()) {
+      @Override
+      public Class<?> loadClass(String name, boolean resolve) throws 
ClassNotFoundException {
+        if ("org.apache.parquet.MissingDependencyClass".equals(name)) {
+          throw new NoClassDefFoundError("some/TransitiveDependency");
+        }
+
+        return super.loadClass(name, resolve);
+      }
+    };
+
+    assertThatThrownBy(() -> new DynMethods.Builder("register")
+            .loader(errorLoader)
+            .impl("org.apache.parquet.MissingDependencyClass")
+            .buildStaticChecked())
+        .isInstanceOf(NoSuchMethodException.class)
+        .hasMessage("Cannot find method: register");
+
+    assertThat(new DynMethods.Builder("register")
+            .loader(errorLoader)
+            .impl("org.apache.parquet.MissingDependencyClass")
+            .impl(Available.class)
+            .buildStaticChecked()
+            .<String>invoke())
+        .isEqualTo("available");
+
+    assertThat(new DynMethods.Builder("register")
+            .loader(errorLoader)
+            .hiddenImpl("org.apache.parquet.MissingDependencyClass")
+            .hiddenImpl(Available.class, "hiddenRegister")
+            .buildStaticChecked()
+            .<String>invoke())
+        .isEqualTo("hidden-available");
+  }
+
+  @Test
+  public void implWithExceptionInInitializerError() {
+    ClassLoader errorLoader = new 
ClassLoader(Thread.currentThread().getContextClassLoader()) {
+      @Override
+      public Class<?> loadClass(String name, boolean resolve) throws 
ClassNotFoundException {
+        throw new ExceptionInInitializerError("static initializer failed");
+      }
+    };
+
+    assertThatThrownBy(() -> new DynMethods.Builder("register")
+            .loader(errorLoader)
+            .impl("org.apache.parquet.FailingInitClass")
+            .buildStaticChecked())
+        .isInstanceOf(ExceptionInInitializerError.class)
+        .hasMessage("static initializer failed");
+  }
 }

Reply via email to