diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/internal/JavaAstProcessor.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/internal/JavaAstProcessor.java index 335d3c8a53..913f53b36e 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/internal/JavaAstProcessor.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/internal/JavaAstProcessor.java @@ -43,6 +43,11 @@ import net.sourceforge.pmd.lang.java.types.internal.infer.TypeInferenceLogger.Ve */ public final class JavaAstProcessor { + /** + * FIXME get rid of that, this prevents both ClassLoader and TypeSystem + * to be garbage-collected, which is an important memory leak. Will be + * fixed by https://github.com/pmd/pmd/issues/3782 (Language Lifecycle) + */ private static final Map TYPE_SYSTEMS = new IdentityHashMap<>(); private static final Level INFERENCE_LOG_LEVEL; diff --git a/pmd-test/src/main/java/net/sourceforge/pmd/testframework/RuleTst.java b/pmd-test/src/main/java/net/sourceforge/pmd/testframework/RuleTst.java index e3a35697ac..d9ceed4b85 100644 --- a/pmd-test/src/main/java/net/sourceforge/pmd/testframework/RuleTst.java +++ b/pmd-test/src/main/java/net/sourceforge/pmd/testframework/RuleTst.java @@ -56,7 +56,12 @@ import net.sourceforge.pmd.util.datasource.DataSource; public abstract class RuleTst { private final DocumentBuilder documentBuilder; + /** Use a single classloader for all tests. */ + private final ClassLoader classpathClassLoader; + public RuleTst() { + classpathClassLoader = makeClassPathClassLoader(); + DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); Schema schema; @@ -87,6 +92,19 @@ public abstract class RuleTst { } } + private ClassLoader makeClassPathClassLoader() { + final ClassLoader classpathClassLoader; + PMDConfiguration config = new PMDConfiguration(); + try { + config.prependClasspath("."); + } catch (IOException ignored) { + + } + classpathClassLoader = config.getClassLoader(); + return classpathClassLoader; + } + + protected void setUp() { // This method is intended to be overridden by subclasses. } @@ -263,7 +281,10 @@ public abstract class RuleTst { if (isUseAuxClasspath) { // configure the "auxclasspath" option for unit testing - configuration.prependClasspath("."); + // we share a single classloader so that pmd-java doesn't create + // a new TypeSystem for every test. This problem will go + // away when languages have a lifecycle. + configuration.setClassLoader(classpathClassLoader); } else { // simple class loader, that doesn't delegate to parent. // this allows us in the tests to simulate PMD run without