From 9d0560531b9b55af288bffea6d8e55f50ea737f1 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Mon, 6 Oct 2025 21:45:42 +0000
Subject: [PATCH 1/2] Initial plan
From 26f4f49d9dcab21ec3cd75813ef225add6ff7525 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Mon, 6 Oct 2025 22:01:25 +0000
Subject: [PATCH 2/2] Fix IllegalAccessException for JDK module classes in
ClassRealm
Fixes module-aware class loading in findClass(String moduleName, String name) to properly delegate to parent/system classloader for JDK module classes. This resolves IllegalAccessException when loading classes like com.sun.jndi.dns.DnsContextFactory through JNDI in Maven plugins.
When moduleName != null, the method now delegates to the parent classloader (or system classloader as fallback) instead of returning null, ensuring proper module context is preserved for JDK internal classes.
Co-authored-by: slachiewicz <6705942+slachiewicz@users.noreply.github.com>
---
.../plexus/classworlds/realm/ClassRealm.java | 18 ++++++++-
.../realm/DefaultClassRealmTest.java | 38 +++++++++++++++++++
2 files changed, 55 insertions(+), 1 deletion(-)
diff --git a/src/main/java/org/codehaus/plexus/classworlds/realm/ClassRealm.java b/src/main/java/org/codehaus/plexus/classworlds/realm/ClassRealm.java
index bbeacee..338a9f7 100644
--- a/src/main/java/org/codehaus/plexus/classworlds/realm/ClassRealm.java
+++ b/src/main/java/org/codehaus/plexus/classworlds/realm/ClassRealm.java
@@ -218,7 +218,23 @@ private Class> unsynchronizedLoadClass(String name, boolean resolve) throws Cl
@SuppressWarnings("Since15")
protected Class> findClass(String moduleName, String name) {
if (moduleName != null) {
- return null;
+ // Delegate to parent for module-aware class loading to maintain proper module context
+ // This is crucial for JDK internal classes like com.sun.jndi.dns.DnsContextFactory
+ ClassLoader parent = getParent();
+ if (parent != null) {
+ try {
+ // Use the parent's module-aware findClass method
+ return parent.loadClass(name);
+ } catch (ClassNotFoundException e) {
+ return null;
+ }
+ }
+ // If no parent, delegate to system classloader for JDK module classes
+ try {
+ return ClassLoader.getSystemClassLoader().loadClass(name);
+ } catch (ClassNotFoundException e) {
+ return null;
+ }
}
try {
return findClassInternal(name);
diff --git a/src/test/java/org/codehaus/plexus/classworlds/realm/DefaultClassRealmTest.java b/src/test/java/org/codehaus/plexus/classworlds/realm/DefaultClassRealmTest.java
index 7751a68..cea373b 100644
--- a/src/test/java/org/codehaus/plexus/classworlds/realm/DefaultClassRealmTest.java
+++ b/src/test/java/org/codehaus/plexus/classworlds/realm/DefaultClassRealmTest.java
@@ -16,9 +16,14 @@
* limitations under the License.
*/
+import javax.naming.Context;
+import javax.naming.directory.DirContext;
+import javax.naming.directory.InitialDirContext;
+
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Collections;
+import java.util.Hashtable;
import java.util.concurrent.CountDownLatch;
import org.codehaus.classworlds.ClassRealmAdapter;
@@ -265,6 +270,39 @@ void testParallelDeadlockClassRealm() throws InterruptedException {
}
}
+ /**
+ * Test that JDK internal classes from named modules (like com.sun.jndi.dns.DnsContextFactory)
+ * can be properly accessed when loaded through ClassRealm. This is crucial for JNDI to work
+ * correctly in Maven plugins.
+ *
+ * @see Issue XX
+ */
+ @Test
+ void testLoadJdkModuleClassThroughJNDI() throws Exception {
+ // Use system classloader as base to ensure JDK module classes can be loaded
+ ClassRealm realm = new ClassRealm(new ClassWorld(), "test", ClassLoader.getSystemClassLoader());
+
+ // Set the thread's context classloader to the realm
+ Thread currentThread = Thread.currentThread();
+ ClassLoader originalClassLoader = currentThread.getContextClassLoader();
+ try {
+ currentThread.setContextClassLoader(realm);
+
+ // Try to instantiate DnsContextFactory via JNDI with explicit factory class name
+ // This is how Netty uses JNDI under Windows
+ Hashtable env = new Hashtable<>();
+ env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.dns.DnsContextFactory");
+ env.put(Context.PROVIDER_URL, "dns:");
+
+ // This should succeed without IllegalAccessException
+ DirContext ctx = new InitialDirContext(env);
+ assertNotNull(ctx);
+ ctx.close();
+ } finally {
+ currentThread.setContextClassLoader(originalClassLoader);
+ }
+ }
+
private void doOneDeadlockAttempt() throws InterruptedException {
// Deadlock sample graciously ripped from http://docs.oracle.com/javase/7/docs/technotes/guides/lang/cl-mt.html
final ClassRealm cl1 = new ClassRealm(new ClassWorld(), "cl1", null);