Don't make redundant ClassLoaderCache instance

I noticed that sometimes multiple ClassLoaderCache instances were
created in each configuraiton. I believe this was due to the use of
inConfig(...)(...) causing multiple caches to be created. Long term, I'm
not sure that taskRepository and classLoaderCache are the right
solutions so I made classLoaderCache private[sbt] as well.
This commit is contained in:
Ethan Atkins 2019-04-01 14:22:33 -07:00
parent 8e1ebda36a
commit 13cdbb5ea6
4 changed files with 10 additions and 15 deletions

View File

@ -1772,7 +1772,7 @@ object Defaults extends BuildCommon {
Classpaths.addUnmanagedLibrary ++
Vector(
TaskRepository.proxy(
classLoaderCache,
Compile / classLoaderCache,
// We need a cache of size four so that the subset of the runtime dependencies that are used
// by the test task layers may be cached without evicting the runtime classloader layers. The
// cache size should be a multiple of two to support snapshot layers.
@ -1783,7 +1783,7 @@ object Defaults extends BuildCommon {
lazy val testSettings: Seq[Setting[_]] = configSettings ++ testTasks ++
Vector(
TaskRepository.proxy(
classLoaderCache,
Test / classLoaderCache,
// We need a cache of size two for the test dependency layers (regular and snapshot).
ClassLoaderCache(2)
)

View File

@ -503,7 +503,7 @@ object Keys {
val resolvedScoped = Def.resolvedScoped
val pluginData = taskKey[PluginData]("Information from the plugin build needed in the main build definition.").withRank(DTask)
val globalPluginUpdate = taskKey[UpdateReport]("A hook to get the UpdateReport of the global plugin.").withRank(DTask)
val classLoaderCache = taskKey[internal.ClassLoaderCache]("The cache of ClassLoaders to be used for layering in tasks that invoke other java code").withRank(DTask)
private[sbt] val classLoaderCache = taskKey[internal.ClassLoaderCache]("The cache of ClassLoaders to be used for layering in tasks that invoke other java code").withRank(DTask)
private[sbt] val taskRepository = AttributeKey[TaskRepository.Repr]("task-repository", "A repository that can be used to cache arbitrary values for a given task key that can be read or filled during task evaluation.", 10000)
private[sbt] val taskCancelStrategy = settingKey[State => TaskCancellationStrategy]("Experimental task cancellation handler.").withRank(DTask)

View File

@ -14,17 +14,17 @@ import sbt.internal.util.TypeFunctions.Id
import scala.annotation.tailrec
sealed trait ClassLoaderCache
private[sbt] sealed trait ClassLoaderCache
extends Repository[Id, (Seq[File], ClassLoader, Map[String, String], File), ClassLoader]
object ClassLoaderCache {
private[sbt] object ClassLoaderCache {
private type Resources = Map[String, String]
private sealed trait CachedClassLoader extends ClassLoader {
def close(): Unit
}
private sealed trait StableClassLoader extends CachedClassLoader
private sealed trait SnapshotClassLoader extends CachedClassLoader
def apply(maxSize: Int): ClassLoaderCache =
def apply(maxSize: Int): ClassLoaderCache = {
new ClassLoaderCache {
private final def mktmp(tmp: File): File =
if (maxSize > 0) Files.createTempDirectory("sbt-jni").toFile else tmp
@ -89,10 +89,5 @@ object ClassLoaderCache {
}
}
}
def empty(newLoader: (Seq[File], ClassLoader, Resources, File) => ClassLoader): ClassLoaderCache =
new ClassLoaderCache {
override def get(key: (Seq[File], ClassLoader, Resources, File)): ClassLoader =
newLoader.tupled(key)
override def close(): Unit = {}
}
}
}

View File

@ -18,7 +18,7 @@ import sbt.internal.inc.classpath.{ ClasspathUtilities, DualLoader, NullLoader }
import sbt.internal.util.Attributed
import sbt.internal.util.Attributed.data
import sbt.io.IO
import sbt.librarymanagement.Configurations.Runtime
import sbt.librarymanagement.Configurations.{ Runtime, Test }
import PrettyPrint.indent
import scala.annotation.tailrec
@ -55,7 +55,7 @@ private[sbt] object ClassLoaders {
dependencyJars(dependencyClasspath).value.filterNot(exclude).toSet,
interfaceLoader,
(Runtime / classLoaderCache).value,
classLoaderCache.value,
(Test / classLoaderCache).value,
ClasspathUtilities.createClasspathResources(fullCP, si),
IO.createUniqueDirectory(taskTemporaryDirectory.value),
resolvedScoped.value.scope
@ -88,7 +88,7 @@ private[sbt] object ClassLoaders {
s.log.warn(s"$showJavaOptions will be ignored, $showFork is set to false")
}
val runtimeCache = (Runtime / classLoaderCache).value
val testCache = classLoaderCache.value
val testCache = (Test / classLoaderCache).value
val exclude = dependencyJars(exportedProducts).value.toSet ++ instance.allJars
val newLoader =
(classpath: Seq[File]) => {