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