Fix OutOfMemory in tests

This did not show up earlier because
we used soft class references, which
reduces the memory footprint of unused
TypeSystems. However, they still remain
in old gen and are a large memory hog.

Since e97e2cd we don't use SoftReference
anymore as parsing the same class several
times may have unintended side-effects.
This revealed the out of memory error.

This will be fixed when we have proper
language lifecycle and resources like the
classloader can be reclaimed later.
This commit is contained in:
Clément Fournier
2022-03-06 18:56:36 +01:00
parent e3fd2782a3
commit 99425d53ff
2 changed files with 27 additions and 1 deletions

View File

@ -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<ClassLoader, TypeSystem> TYPE_SYSTEMS = new IdentityHashMap<>();
private static final Level INFERENCE_LOG_LEVEL;

View File

@ -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