diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/internal/util/ClasspathClassLoader.java b/pmd-core/src/main/java/net/sourceforge/pmd/internal/util/ClasspathClassLoader.java index 4a17f6550a..024542c01f 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/internal/util/ClasspathClassLoader.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/internal/util/ClasspathClassLoader.java @@ -116,8 +116,9 @@ public class ClasspathClassLoader extends URLClassLoader { URL url = findResource(name); if (url == null) { - // note this will actually call back into findResource, but - // we can't avoid this as the super call + // note this will actually call back into this.findResource, but + // we can't avoid this as the super implementation uses JDK internal + // stuff that we can't copy down here. return super.getResource(name); } return url; diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/symbols/ClassLoadingChildFirstTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/symbols/ClassLoadingChildFirstTest.java new file mode 100644 index 0000000000..692edadee8 --- /dev/null +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/symbols/ClassLoadingChildFirstTest.java @@ -0,0 +1,55 @@ +/* + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package net.sourceforge.pmd.lang.java.symbols; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.hasProperty; +import static org.hamcrest.Matchers.hasSize; + +import java.net.URL; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.List; + +import org.junit.jupiter.api.Test; + +import net.sourceforge.pmd.PMDConfiguration; +import net.sourceforge.pmd.internal.util.ClasspathClassLoader; +import net.sourceforge.pmd.lang.java.types.JClassType; +import net.sourceforge.pmd.lang.java.types.TypeSystem; + +/** + * @author Clément Fournier + */ +class ClassLoadingChildFirstTest { + + + /** + * In this test I packed a jar with a custom version of {@link Void}. + * The test asserts that when putting that jar on the auxclasspath, + * a {@link TypeSystem} prefers that custom class to the one on the + * bootstrap classpath. The functionality under test is actually in + * {@link ClasspathClassLoader}. + */ + @Test + void testClassLoading() { + String jarPath = getClass().getPackage().getName().replace('.', '/') + "/custom_java_lang.jar"; + URL url = Thread.currentThread().getContextClassLoader().getResource(jarPath); + Path file = Paths.get(url.getPath()); + + PMDConfiguration config = new PMDConfiguration(); + config.prependAuxClasspath(file.toAbsolutePath().toString()); + + TypeSystem typeSystem = TypeSystem.usingClassLoaderClasspath(config.getClassLoader()); + + JClassType voidClass = typeSystem.BOXED_VOID; + List declaredMethods = voidClass.getSymbol().getDeclaredMethods(); + assertThat(declaredMethods, hasSize(1)); + assertThat(declaredMethods.get(0), hasProperty("simpleName", equalTo("customMethodOnJavaLangVoid"))); + + } + +} diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/symbols/custom_java_lang.jar b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/symbols/custom_java_lang.jar new file mode 100644 index 0000000000..5b665d8056 Binary files /dev/null and b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/symbols/custom_java_lang.jar differ