diff --git a/build.sbt b/build.sbt index 4e812dcc..e5329521 100644 --- a/build.sbt +++ b/build.sbt @@ -29,7 +29,11 @@ def commonSettings: Seq[Setting[_]] = Seq( }, publishArtifact in Compile := true, publishArtifact in Test := false, - parallelExecution in Test := false + parallelExecution in Test := false, + testOptions in Test += { + val log = streams.value.log + Tests.Cleanup { loader => cleanupTests(loader, log) } + } ) val mimaSettings = Def settings ( @@ -232,3 +236,21 @@ def customCommands: Seq[Setting[_]] = Seq( state } ) + +// TODO move into sbt-house-rules? +def cleanupTests(loader: ClassLoader, log: sbt.internal.util.ManagedLogger): Unit = { + // shutdown Log4J to avoid classloader leaks + try { + val logManager = Class.forName("org.apache.logging.log4j.LogManager") + logManager.getMethod("shutdown").invoke(null) + } catch { + case _: Throwable => + log.warn("Could not shut down Log4J") + } + // Scala Test loads property bundles, let's eagerly clear then from the internal cache + // TODO move into SBT itself? + java.util.ResourceBundle.clearCache(loader) + // Scala Test also starts TimerThreads that it doesn't eagerly cancel. This can weakly retain + // metaspace until a full GC. + System.gc() +} \ No newline at end of file