From 862ae293ba6ba16ab8fd06db057ae496703f64da Mon Sep 17 00:00:00 2001 From: Eugene Yokota Date: Fri, 2 Mar 2018 00:42:00 -0500 Subject: [PATCH] include only scala-library into the boot classpath during run Fixes https://github.com/sbt/sbt/issues/3405 Ref https://github.com/scala/scala-xml/issues/195 sbt's `run` is emulated using a classloader trick that includes ScalaInstance as the parent classloader under the classpath. The problem is the ScalaInstance classloader currently contains both compiler, library, and their transitive JARs: ```scala res0: Array[java.io.File] = Array(scala-library.jar, scala-compiler.jar, jline.jar, scala-reflect.jar, scala-xml_2.12.jar) ``` This could have been causing various issues, but most recently it showed up as wrong version of scala-xml getting prioritized over what's passed by the user. 1. new field loaderLibraryOnly is added to xsbti.ScalaInstance. 2. it is initialized to the library loader if the launcher creates it, otherwise create layered loader here. This aims to isolate the library loader, and retain the perf. --- .../sbt/internal/inc/ZincComponentCompiler.scala | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ZincComponentCompiler.scala b/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ZincComponentCompiler.scala index 234a9c3a9..f51672038 100644 --- a/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ZincComponentCompiler.scala +++ b/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ZincComponentCompiler.scala @@ -140,11 +140,19 @@ private[sbt] object ZincComponentCompiler { val scalaLibrary = scalaArtifacts.library val jarsToLoad = (scalaCompiler +: scalaLibrary +: scalaArtifacts.others).toArray assert(jarsToLoad.forall(_.exists), "One or more jar(s) in the Scala instance do not exist.") - val loader = new URLClassLoader(toURLs(jarsToLoad), ClasspathUtilities.rootLoader) + val loaderLibraryOnly = ClasspathUtilities.toLoader(Vector(scalaLibrary)) + val loader = ClasspathUtilities.toLoader(jarsToLoad.toVector filterNot { _ == scalaLibrary }, + loaderLibraryOnly) val properties = ResourceLoader.getSafePropertiesFor("compiler.properties", loader) val loaderVersion = Option(properties.getProperty("version.number")) val scalaV = loaderVersion.getOrElse("unknown") - new ScalaInstance(scalaV, loader, scalaLibrary, scalaCompiler, jarsToLoad, loaderVersion) + new ScalaInstance(scalaV, + loader, + loaderLibraryOnly, + scalaLibrary, + scalaCompiler, + jarsToLoad, + loaderVersion) } }