From 04b0699cd5b97905c95da2d2f140ec09d8b9971f Mon Sep 17 00:00:00 2001 From: Maxim Shafirov Date: Thu, 2 Feb 2012 20:35:15 +0400 Subject: [PATCH] Fix memory leak by disposing a classloader. The real issue though is located in TypeInfoParser, that has WeakHashMap with values referencing keys. --- .../jetbrains/jet/codegen/GeneratedClassLoader.java | 6 +++++- .../jetbrains/jet/compiler/CompileEnvironment.java | 8 ++++++-- .../org/jetbrains/jet/codegen/CodegenTestCase.java | 12 ++++++++---- .../tests/org/jetbrains/jet/codegen/TestlibTest.java | 11 +++++++++-- 4 files changed, 28 insertions(+), 9 deletions(-) diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/GeneratedClassLoader.java b/compiler/backend/src/org/jetbrains/jet/codegen/GeneratedClassLoader.java index ec8a3eaffdd..baaf816bb3d 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/GeneratedClassLoader.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/GeneratedClassLoader.java @@ -6,7 +6,7 @@ import org.jetbrains.annotations.NotNull; * @author yole */ public class GeneratedClassLoader extends ClassLoader { - private final ClassFileFactory state; + private ClassFileFactory state; public GeneratedClassLoader(@NotNull ClassFileFactory state) { this(state, GeneratedClassLoader.class.getClassLoader()); @@ -26,4 +26,8 @@ public class GeneratedClassLoader extends ClassLoader { } return super.findClass(name); } + + public void dispose() { + state = null; + } } diff --git a/compiler/cli/src/org/jetbrains/jet/compiler/CompileEnvironment.java b/compiler/cli/src/org/jetbrains/jet/compiler/CompileEnvironment.java index 80dc47f2098..25a5427aaec 100644 --- a/compiler/cli/src/org/jetbrains/jet/compiler/CompileEnvironment.java +++ b/compiler/cli/src/org/jetbrains/jet/compiler/CompileEnvironment.java @@ -174,7 +174,7 @@ public class CompileEnvironment { } private List runDefineModules(String moduleFile, ClassFileFactory factory) { - ClassLoader loader = myStdlib != null ? new GeneratedClassLoader(factory, new URLClassLoader(new URL[] {myStdlib}, AllModules.class.getClassLoader())) : new GeneratedClassLoader(factory); + GeneratedClassLoader loader = myStdlib != null ? new GeneratedClassLoader(factory, new URLClassLoader(new URL[] {myStdlib}, AllModules.class.getClassLoader())) : new GeneratedClassLoader(factory); try { Class namespaceClass = loader.loadClass(JvmAbi.PACKAGE_CLASS); final Method method = namespaceClass.getDeclaredMethod("project"); @@ -188,9 +188,13 @@ public class CompileEnvironment { ArrayList answer = new ArrayList(AllModules.modules); AllModules.modules.clear(); return answer; - } catch (Exception e) { + } + catch (Exception e) { throw new ModuleExecutionException(e); } + finally { + loader.dispose(); + } } public ClassFileFactory compileModule(Module moduleBuilder, String directory) { diff --git a/compiler/tests/org/jetbrains/jet/codegen/CodegenTestCase.java b/compiler/tests/org/jetbrains/jet/codegen/CodegenTestCase.java index 75c7f2d618c..b905f030458 100644 --- a/compiler/tests/org/jetbrains/jet/codegen/CodegenTestCase.java +++ b/compiler/tests/org/jetbrains/jet/codegen/CodegenTestCase.java @@ -91,10 +91,14 @@ public abstract class CodegenTestCase extends JetLiteFixture { ClassFileFactory codegens = generateClassesInFile(); GeneratedClassLoader loader = new GeneratedClassLoader(codegens); - String fqName = NamespaceCodegen.getJVMClassName(JetPsiUtil.getFQName(myFile), true).replace("/", "."); - Class namespaceClass = loader.loadClass(fqName); - Method method = namespaceClass.getMethod("box"); - return (String) method.invoke(null); + try { + String fqName = NamespaceCodegen.getJVMClassName(JetPsiUtil.getFQName(myFile), true).replace("/", "."); + Class namespaceClass = loader.loadClass(fqName); + Method method = namespaceClass.getMethod("box"); + return (String) method.invoke(null); + } finally { + loader.dispose(); + } } protected String generateToText() { diff --git a/compiler/tests/org/jetbrains/jet/codegen/TestlibTest.java b/compiler/tests/org/jetbrains/jet/codegen/TestlibTest.java index 525ab1594c1..32cdc787a9f 100644 --- a/compiler/tests/org/jetbrains/jet/codegen/TestlibTest.java +++ b/compiler/tests/org/jetbrains/jet/codegen/TestlibTest.java @@ -4,6 +4,7 @@ import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.vfs.local.CoreLocalFileSystem; import gnu.trove.THashSet; import junit.framework.TestCase; +import junit.framework.TestResult; import junit.framework.TestSuite; import org.jetbrains.jet.compiler.CompileSession; import org.jetbrains.jet.lang.descriptors.ClassDescriptor; @@ -74,13 +75,19 @@ public class TestlibTest extends CodegenTestCase { ClassFileFactory classFileFactory = session.generate(); - GeneratedClassLoader loader = new GeneratedClassLoader( + final GeneratedClassLoader loader = new GeneratedClassLoader( classFileFactory, new URLClassLoader(new URL[]{ForTestCompileStdlib.stdlibJarForTests().toURI().toURL(), junitJar.toURI().toURL()}, TestCase.class.getClassLoader())); JetTypeMapper typeMapper = new JetTypeMapper(classFileFactory.state.getStandardLibrary(), session.getMyBindingContext()); - TestSuite suite = new TestSuite("StandardLibrary"); + TestSuite suite = new TestSuite("StandardLibrary") { + @Override + public void run(TestResult result) { + super.run(result); + loader.dispose(); + } + }; try { for(JetFile jetFile : session.getSourceFileNamespaces()) { for(JetDeclaration decl : jetFile.getDeclarations()) {