diff --git a/core/src/main/java/org/jruby/Ruby.java b/core/src/main/java/org/jruby/Ruby.java index 200dea42fe4..86f8058fa0e 100644 --- a/core/src/main/java/org/jruby/Ruby.java +++ b/core/src/main/java/org/jruby/Ruby.java @@ -3402,6 +3402,18 @@ private void systemTeardown(final ThreadContext context) { threadService.teardown(); threadService = new ThreadService(this); + // Release classloader resources + releaseClassLoader(); + + // Tear down LoadService + loadService.tearDown(); + + // Clear runtime tables to aid GC + boundMethods.clear(); + allModules.clear(); + constantNameInvalidators.clear(); + symbolTable.clear(); + javaSupport = loadJavaSupport(); } private int userTeardown(ThreadContext context) { @@ -3454,7 +3466,6 @@ private int userTeardown(ThreadContext context) { public void releaseClassLoader() { if (jrubyClassLoader != null) { jrubyClassLoader.close(); - //jrubyClassLoader = null; } } @@ -5625,7 +5636,7 @@ public RubyClass getData() { private PrintStream err; // Java support - private final JavaSupport javaSupport; + private JavaSupport javaSupport; private final JRubyClassLoader jrubyClassLoader; // Object Specializer diff --git a/core/src/main/java/org/jruby/RubySymbol.java b/core/src/main/java/org/jruby/RubySymbol.java index 11654541202..cff00bcc002 100644 --- a/core/src/main/java/org/jruby/RubySymbol.java +++ b/core/src/main/java/org/jruby/RubySymbol.java @@ -996,8 +996,7 @@ public static final class SymbolTable { public SymbolTable(Ruby runtime) { this.runtime = runtime; this.loadFactor = DEFAULT_LOAD_FACTOR; - this.threshold = (int)(DEFAULT_INITIAL_CAPACITY * DEFAULT_LOAD_FACTOR); - this.symbolTable = new SymbolEntry[DEFAULT_INITIAL_CAPACITY]; + reset(); } // note all fields are final -- rehash creates new entries when necessary. @@ -1337,6 +1336,15 @@ public int size() { return size; } + public void clear() { + reset(); + } + + private void reset() { + this.threshold = (int)(DEFAULT_INITIAL_CAPACITY * DEFAULT_LOAD_FACTOR); + this.symbolTable = new SymbolEntry[DEFAULT_INITIAL_CAPACITY]; + } + private SymbolEntry[] rehash() { SymbolEntry[] oldTable = symbolTable; int oldCapacity = oldTable.length; diff --git a/core/src/main/java/org/jruby/embed/ScriptingContainer.java b/core/src/main/java/org/jruby/embed/ScriptingContainer.java index 32dbea57fe1..237fb7c61d5 100644 --- a/core/src/main/java/org/jruby/embed/ScriptingContainer.java +++ b/core/src/main/java/org/jruby/embed/ScriptingContainer.java @@ -1844,7 +1844,6 @@ public void terminate() { LocalContextProvider provider = getProvider(); if (provider.isRuntimeInitialized()) { provider.getRuntime().tearDown(false); - provider.getRuntime().releaseClassLoader(); } provider.terminate(); } diff --git a/core/src/main/java/org/jruby/runtime/load/LibrarySearcher.java b/core/src/main/java/org/jruby/runtime/load/LibrarySearcher.java index 96500bb034a..a8a4155bcaa 100644 --- a/core/src/main/java/org/jruby/runtime/load/LibrarySearcher.java +++ b/core/src/main/java/org/jruby/runtime/load/LibrarySearcher.java @@ -808,6 +808,12 @@ private static boolean isURI(String path) { return false; } + // Clear caches and release resources + public void tearDown() { + loadedFeaturesIndex.clear(); + loadedFeaturesSnapshot.clear(); + } + enum Suffix { RUBY(".rb", ResourceLibrary::new), CLASS(".class", ClassResourceLibrary::new), diff --git a/core/src/main/java/org/jruby/runtime/load/LoadService.java b/core/src/main/java/org/jruby/runtime/load/LoadService.java index 79658741ea2..0f5bcb26433 100644 --- a/core/src/main/java/org/jruby/runtime/load/LoadService.java +++ b/core/src/main/java/org/jruby/runtime/load/LoadService.java @@ -1009,4 +1009,9 @@ public String getPathForLocation(String filename) { return filename; } + + public void tearDown() { + loadedFeatures.clear(); + librarySearcher.tearDown(); + } }