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);