@@ -29,7 +29,11 @@ def commonSettings: Seq[Setting[_]] = Seq(
29
29
},
30
30
publishArtifact in Compile := true ,
31
31
publishArtifact in Test := false ,
32
- parallelExecution in Test := false
32
+ parallelExecution in Test := false ,
33
+ testOptions in Test += {
34
+ val log = streams.value.log
35
+ Tests .Cleanup { loader => cleanupTests(loader, log) }
36
+ }
33
37
)
34
38
35
39
val mimaSettings = Def settings (
@@ -232,3 +236,21 @@ def customCommands: Seq[Setting[_]] = Seq(
232
236
state
233
237
}
234
238
)
239
+
240
+ // TODO move into sbt-house-rules?
241
+ def cleanupTests (loader : ClassLoader , log : sbt.internal.util.ManagedLogger ): Unit = {
242
+ // shutdown Log4J to avoid classloader leaks
243
+ try {
244
+ val logManager = Class .forName(" org.apache.logging.log4j.LogManager" )
245
+ logManager.getMethod(" shutdown" ).invoke(null )
246
+ } catch {
247
+ case _ : Throwable =>
248
+ log.warn(" Could not shut down Log4J" )
249
+ }
250
+ // Scala Test loads property bundles, let's eagerly clear then from the internal cache
251
+ // TODO move into SBT itself?
252
+ java.util.ResourceBundle .clearCache(loader)
253
+ // Scala Test also starts TimerThreads that it doesn't eagerly cancel. This can weakly retain
254
+ // metaspace until a full GC.
255
+ System .gc()
256
+ }
0 commit comments