mirror of https://github.com/sbt/sbt.git
Properly close a number of classloaders
I discovered there were a number of places where closing a ClassLoader didn't work correctly because I was assuming it was a URLClassLoader when it was actually a ClasspathFilter. I also incorrectly imported the wrong kind of URLClassLoader in Run.scala. Finally, I close the SbtMetaBuildClassLoader when xMain exits now.
This commit is contained in:
parent
bc21db2864
commit
67df72ab01
|
|
@ -29,6 +29,7 @@ import sbt.Scope.{ GlobalScope, ThisScope, fillTaskAxis }
|
||||||
import sbt.internal.CommandStrings.ExportStream
|
import sbt.internal.CommandStrings.ExportStream
|
||||||
import sbt.internal._
|
import sbt.internal._
|
||||||
import sbt.internal.inc.JavaInterfaceUtil._
|
import sbt.internal.inc.JavaInterfaceUtil._
|
||||||
|
import sbt.internal.inc.classpath.ClasspathFilter
|
||||||
import sbt.internal.inc.{ ZincLmUtil, ZincUtil }
|
import sbt.internal.inc.{ ZincLmUtil, ZincUtil }
|
||||||
import sbt.internal.io.{ Source, WatchState }
|
import sbt.internal.io.{ Source, WatchState }
|
||||||
import sbt.internal.librarymanagement.{ CustomHttp => _, _ }
|
import sbt.internal.librarymanagement.{ CustomHttp => _, _ }
|
||||||
|
|
@ -795,13 +796,17 @@ object Defaults extends BuildCommon {
|
||||||
// ((streams in test, loadedTestFrameworks, testLoader, testGrouping in test, testExecution in test, fullClasspath in test, javaHome in test, testForkedParallel, javaOptions in test) flatMap allTestGroupsTask).value,
|
// ((streams in test, loadedTestFrameworks, testLoader, testGrouping in test, testExecution in test, fullClasspath in test, javaHome in test, testForkedParallel, javaOptions in test) flatMap allTestGroupsTask).value,
|
||||||
testResultLogger in (Test, test) :== TestResultLogger.SilentWhenNoTests, // https://github.com/sbt/sbt/issues/1185
|
testResultLogger in (Test, test) :== TestResultLogger.SilentWhenNoTests, // https://github.com/sbt/sbt/issues/1185
|
||||||
test := {
|
test := {
|
||||||
val loader = testLoader.value match { case u: URLClassLoader => Some(u); case _ => None }
|
val close = testLoader.value match {
|
||||||
|
case u: URLClassLoader => Some(() => u.close())
|
||||||
|
case c: ClasspathFilter => Some(() => c.close())
|
||||||
|
case _ => None
|
||||||
|
}
|
||||||
val trl = (testResultLogger in (Test, test)).value
|
val trl = (testResultLogger in (Test, test)).value
|
||||||
val taskName = Project.showContextKey(state.value).show(resolvedScoped.value)
|
val taskName = Project.showContextKey(state.value).show(resolvedScoped.value)
|
||||||
try {
|
try {
|
||||||
trl.run(streams.value.log, executeTests.value, taskName)
|
trl.run(streams.value.log, executeTests.value, taskName)
|
||||||
} finally {
|
} finally {
|
||||||
loader.foreach(_.close())
|
close.foreach(_.apply())
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
testOnly := inputTests(testOnly).evaluated,
|
testOnly := inputTests(testOnly).evaluated,
|
||||||
|
|
|
||||||
|
|
@ -50,6 +50,11 @@ final class xMain extends xsbti.AppMain {
|
||||||
case e: InvocationTargetException =>
|
case e: InvocationTargetException =>
|
||||||
// This propogates xsbti.FullReload to the launcher
|
// This propogates xsbti.FullReload to the launcher
|
||||||
throw e.getCause
|
throw e.getCause
|
||||||
|
} finally {
|
||||||
|
loader match {
|
||||||
|
case a: AutoCloseable => a.close()
|
||||||
|
case _ =>
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
|
|
|
||||||
|
|
@ -226,6 +226,11 @@ private[sbt] object SbtMetaBuildClassLoader {
|
||||||
}
|
}
|
||||||
new URLClassLoader(rest, updatedLibraryLoader) {
|
new URLClassLoader(rest, updatedLibraryLoader) {
|
||||||
override def toString: String = s"SbtMetaBuildClassLoader"
|
override def toString: String = s"SbtMetaBuildClassLoader"
|
||||||
|
override def close(): Unit = {
|
||||||
|
super.close()
|
||||||
|
updatedLibraryLoader.close()
|
||||||
|
interfaceLoader.close()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,19 +8,19 @@
|
||||||
package sbt
|
package sbt
|
||||||
|
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.lang.reflect.{ Method, Modifier }
|
import java.lang.reflect.Method
|
||||||
import Modifier.{ isPublic, isStatic }
|
import java.lang.reflect.Modifier.{ isPublic, isStatic }
|
||||||
|
import java.net.URLClassLoader
|
||||||
|
|
||||||
import sbt.internal.inc.classpath.ClasspathUtilities
|
|
||||||
import sbt.internal.inc.ScalaInstance
|
import sbt.internal.inc.ScalaInstance
|
||||||
|
import sbt.internal.inc.classpath.{ ClasspathFilter, ClasspathUtilities }
|
||||||
import sbt.internal.util.MessageOnlyException
|
import sbt.internal.util.MessageOnlyException
|
||||||
import sbt.io.Path
|
import sbt.io.Path
|
||||||
import sbt.util.Logger
|
import sbt.util.Logger
|
||||||
|
|
||||||
import scala.reflect.internal.util.ScalaClassLoader.URLClassLoader
|
|
||||||
import scala.util.{ Failure, Success, Try }
|
|
||||||
import scala.util.control.NonFatal
|
|
||||||
import scala.sys.process.Process
|
import scala.sys.process.Process
|
||||||
|
import scala.util.control.NonFatal
|
||||||
|
import scala.util.{ Failure, Success, Try }
|
||||||
|
|
||||||
sealed trait ScalaRun {
|
sealed trait ScalaRun {
|
||||||
def run(mainClass: String, classpath: Seq[File], options: Seq[String], log: Logger): Try[Unit]
|
def run(mainClass: String, classpath: Seq[File], options: Seq[String], log: Logger): Try[Unit]
|
||||||
|
|
@ -98,8 +98,9 @@ class Run(newLoader: Seq[File] => ClassLoader, trapExit: Boolean) extends ScalaR
|
||||||
invokeMain(loader, main, options)
|
invokeMain(loader, main, options)
|
||||||
} finally {
|
} finally {
|
||||||
loader match {
|
loader match {
|
||||||
case u: URLClassLoader => u.close()
|
case u: URLClassLoader => u.close()
|
||||||
case _ =>
|
case c: ClasspathFilter => c.close()
|
||||||
|
case _ =>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue