From cfa29bafe715666ab3a8ea04c232f0fe75fe9bf5 Mon Sep 17 00:00:00 2001 From: Ethan Atkins Date: Tue, 24 Sep 2019 11:42:07 -0700 Subject: [PATCH] Close classloader in ScalaRun.run It is necessary to close the run classloader in order to reuse the dependency layer in the next run. If the loader needs to survive past the main method, as is the case with `run` and `runMain`, then the runWithLoader api should be used instead. This mostly restores the behavior of classloader closing to 1.3.0 for the tasks that use ScalaRun except for `run` and `runMain`. But unlike 1.3.0, if the classloader is closed it can still spawn a zombie classloader. Fixes #5124. --- run/src/main/scala/sbt/Run.scala | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/run/src/main/scala/sbt/Run.scala b/run/src/main/scala/sbt/Run.scala index 8e635ae03..12e1efd01 100644 --- a/run/src/main/scala/sbt/Run.scala +++ b/run/src/main/scala/sbt/Run.scala @@ -12,7 +12,7 @@ import java.lang.reflect.Method import java.lang.reflect.Modifier.{ isPublic, isStatic } import sbt.internal.inc.ScalaInstance -import sbt.internal.inc.classpath.ClasspathUtilities +import sbt.internal.inc.classpath.{ ClasspathFilter, ClasspathUtilities } import sbt.internal.util.MessageOnlyException import sbt.io.Path import sbt.util.Logger @@ -95,7 +95,13 @@ class Run(private[sbt] val newLoader: Seq[File] => ClassLoader, trapExit: Boolea /** Runs the class 'mainClass' using the given classpath and options using the scala runner.*/ def run(mainClass: String, classpath: Seq[File], options: Seq[String], log: Logger): Try[Unit] = { - runWithLoader(newLoader(classpath), classpath, mainClass, options, log) + val loader = newLoader(classpath) + try runWithLoader(loader, classpath, mainClass, options, log) + finally loader match { + case ac: AutoCloseable => ac.close() + case c: ClasspathFilter => c.close() + case _ => + } } private def invokeMain( loader: ClassLoader,