From b00c675a19521e498ac50a3298e5fa2a980c6880 Mon Sep 17 00:00:00 2001 From: Eugene Yokota Date: Sun, 12 May 2019 23:35:31 -0400 Subject: [PATCH 1/2] change ClassLoaderLayeringStrategy.ScalaInstance to ScalaLibrary Fixes #4609 ScalaInstance contains unwanted Scala modules such as scala-xml and scala-parser-combinators. --- .../sbt/ClassLoaderLayeringStrategy.scala | 30 +++++++++---------- main/src/main/scala/sbt/Defaults.scala | 6 ++-- .../scala/sbt/internal/ClassLoaders.scala | 12 ++++---- .../classloader-cache/package-private/test | 2 +- .../classloader-cache/runtime-layers/test | 4 +-- 5 files changed, 27 insertions(+), 27 deletions(-) diff --git a/main/src/main/scala/sbt/ClassLoaderLayeringStrategy.scala b/main/src/main/scala/sbt/ClassLoaderLayeringStrategy.scala index 7245c2e8b..b32eb44fd 100644 --- a/main/src/main/scala/sbt/ClassLoaderLayeringStrategy.scala +++ b/main/src/main/scala/sbt/ClassLoaderLayeringStrategy.scala @@ -77,47 +77,47 @@ object ClassLoaderLayeringStrategy { case object Flat extends ClassLoaderLayeringStrategy /** - * Add a layer for the scala instance class loader. + * Add a layer for the scala library class loader. */ - sealed trait ScalaInstance extends ClassLoaderLayeringStrategy + sealed trait ScalaLibrary extends ClassLoaderLayeringStrategy /** * This should indicate that we use a two layer ClassLoader where the top layer is the scala * instance and all of the dependencies and project class paths are included in the search path * of the second layer. */ - case object ScalaInstance extends ScalaInstance + case object ScalaLibrary extends ScalaLibrary /** - * Add a layer on top of the ScalaInstance layer for the runtime jar dependencies. + * Add a layer on top of the ScalaLibrary layer for the runtime jar dependencies. */ - sealed trait RuntimeDependencies extends ScalaInstance + sealed trait RuntimeDependencies extends ScalaLibrary /** - * Add a layer on top of the ScalaInstance layer for the runtime jar dependencies. + * Add a layer on top of the ScalaLibrary layer for the runtime jar dependencies. */ - case object RuntimeDependencies extends ScalaInstance with RuntimeDependencies + case object RuntimeDependencies extends ScalaLibrary with RuntimeDependencies + + /** + * Add a layer on top of the ScalaLibrary layer for the test jar dependencies. + */ + sealed trait TestDependencies extends ScalaLibrary /** * Add a layer on top of the ScalaInstance layer for the test jar dependencies. */ - sealed trait TestDependencies extends ScalaInstance - - /** - * Add a layer on top of the ScalaInstance layer for the test jar dependencies. - */ - case object TestDependencies extends ScalaInstance with TestDependencies + case object TestDependencies extends ScalaLibrary with TestDependencies /** * Add the TestDependencies layer on top of the RuntimeDependencies layer on top of the - * ScalaInstance layer. This differs from TestDependencies in that it will not reload the + * ScalaLibrary layer. This differs from TestDependencies in that it will not reload the * runtime classpath. The drawback to using this is that if the test dependencies evict * classes provided in the runtime layer, then tests can fail. In order for sharing the runtime * layer to work, it is necessary to set [[Keys.bgCopyClasspath]] to false. Otherwise the * runtime and test classpaths are completely different. */ case object ShareRuntimeDependenciesLayerWithTestDependencies - extends ScalaInstance + extends ScalaLibrary with RuntimeDependencies with TestDependencies diff --git a/main/src/main/scala/sbt/Defaults.scala b/main/src/main/scala/sbt/Defaults.scala index b5998b176..eff05ef36 100755 --- a/main/src/main/scala/sbt/Defaults.scala +++ b/main/src/main/scala/sbt/Defaults.scala @@ -1091,7 +1091,7 @@ object Defaults extends BuildCommon { out.events.foreach { case (suite, e) => if (strategy != ClassLoaderLayeringStrategy.Flat || - strategy != ClassLoaderLayeringStrategy.ScalaInstance) { + strategy != ClassLoaderLayeringStrategy.ScalaLibrary) { (e.throwables ++ e.throwables.flatMap(t => Option(t.getCause))) .find { t => t.isInstanceOf[NoClassDefFoundError] || @@ -1116,11 +1116,11 @@ object Defaults extends BuildCommon { + " jvm enforces package private at the classloader level.\n\n" + "These issues, along with others that were not enumerated above, may be" + " resolved by changing the class loader layering strategy.\n" - + "The Flat and ScalaInstance strategies bundle the full project classpath in" + + "The Flat and ScalaLibrary strategies bundle the full project classpath in" + " the same class loader.\nTo use one of these strategies, set the " + " ClassLoaderLayeringStrategy key\nin your configuration, for example:\n\n" + s"set ${projectId}Test / classLoaderLayeringStrategy :=" - + " ClassLoaderLayeringStrategy.ScalaInstance\n" + + " ClassLoaderLayeringStrategy.ScalaLibrary\n" + s"set ${projectId}Test / classLoaderLayeringStrategy :=" + " ClassLoaderLayeringStrategy.Flat\n\n" + "See ClassLoaderLayeringStrategy.scala for the full list of options." diff --git a/main/src/main/scala/sbt/internal/ClassLoaders.scala b/main/src/main/scala/sbt/internal/ClassLoaders.scala index 0222c1da5..c486800ba 100644 --- a/main/src/main/scala/sbt/internal/ClassLoaders.scala +++ b/main/src/main/scala/sbt/internal/ClassLoaders.scala @@ -11,7 +11,7 @@ package internal import java.io.File import java.net.{ URL, URLClassLoader } -import sbt.ClassLoaderLayeringStrategy.{ ScalaInstance => ScalaInstanceLayer, _ } +import sbt.ClassLoaderLayeringStrategy._ import sbt.Keys._ import sbt.SlashSyntax0._ import sbt.internal.inc.ScalaInstance @@ -130,7 +130,7 @@ private[sbt] object ClassLoaders { case _ => val (layerDependencies, layerTestDependencies) = strategy match { case ShareRuntimeDependenciesLayerWithTestDependencies if isTest => (true, true) - case ScalaInstanceLayer => (false, false) + case ScalaLibrary => (false, false) case RuntimeDependencies => (true, false) case TestDependencies if isTest => (false, true) case badStrategy => @@ -147,15 +147,15 @@ private[sbt] object ClassLoaders { val allTestDependencies = if (layerTestDependencies) allDependenciesSet else Set.empty[File] val allRuntimeDependencies = (if (layerDependencies) rawRuntimeDependencies else Nil).toSet - val scalaInstanceLayer = - globalCache.get((si.allJars.toSeq, interfaceLoader, resources, tmp)) + val scalaLibraryLayer = + globalCache.get((List(si.libraryJar), interfaceLoader, resources, tmp)) // layer 2 val runtimeDependencySet = allDependenciesSet intersect allRuntimeDependencies val runtimeDependencies = rawRuntimeDependencies.filter(runtimeDependencySet) lazy val runtimeLayer = if (layerDependencies) - layer(runtimeDependencies, scalaInstanceLayer, runtimeCache, resources, tmp) - else scalaInstanceLayer + layer(runtimeDependencies, scalaLibraryLayer, runtimeCache, resources, tmp) + else scalaLibraryLayer // layer 3 (optional if testDependencies are empty) val testDependencySet = allTestDependencies diff runtimeDependencySet diff --git a/sbt/src/sbt-test/classloader-cache/package-private/test b/sbt/src/sbt-test/classloader-cache/package-private/test index bda116d0c..64ef9d785 100644 --- a/sbt/src/sbt-test/classloader-cache/package-private/test +++ b/sbt/src/sbt-test/classloader-cache/package-private/test @@ -4,6 +4,6 @@ > run -> set Runtime / classLoaderLayeringStrategy := ClassLoaderLayeringStrategy.ScalaInstance +> set Runtime / classLoaderLayeringStrategy := ClassLoaderLayeringStrategy.ScalaLibrary > run diff --git a/sbt/src/sbt-test/classloader-cache/runtime-layers/test b/sbt/src/sbt-test/classloader-cache/runtime-layers/test index 6a598d358..8ba3debaa 100644 --- a/sbt/src/sbt-test/classloader-cache/runtime-layers/test +++ b/sbt/src/sbt-test/classloader-cache/runtime-layers/test @@ -4,7 +4,7 @@ > run -> set Compile / classLoaderLayeringStrategy := ClassLoaderLayeringStrategy.ScalaInstance +> set Compile / classLoaderLayeringStrategy := ClassLoaderLayeringStrategy.ScalaLibrary > run @@ -20,7 +20,7 @@ > Test / runMain sbt.scripted.TestAkkaTest -> set Test / classLoaderLayeringStrategy := ClassLoaderLayeringStrategy.ScalaInstance +> set Test / classLoaderLayeringStrategy := ClassLoaderLayeringStrategy.ScalaLibrary > Test / runMain sbt.scripted.TestAkkaTest From 5c85c04e0d0ccda5ddf4cb5aa33433aaadde23c3 Mon Sep 17 00:00:00 2001 From: Eugene Yokota Date: Sun, 12 May 2019 23:51:17 -0400 Subject: [PATCH 2/2] don't include si.allJars into the test classpath allJars contains unwanted Scala modules. Having this in prevents the flat classloader from working correctly. Ref #4609 --- main/src/main/scala/sbt/internal/ClassLoaders.scala | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/main/src/main/scala/sbt/internal/ClassLoaders.scala b/main/src/main/scala/sbt/internal/ClassLoaders.scala index c486800ba..35a9b5da3 100644 --- a/main/src/main/scala/sbt/internal/ClassLoaders.scala +++ b/main/src/main/scala/sbt/internal/ClassLoaders.scala @@ -31,8 +31,8 @@ private[sbt] object ClassLoaders { private[sbt] def testTask: Def.Initialize[Task[ClassLoader]] = Def.task { val si = scalaInstance.value val rawCP = data(fullClasspath.value) - val fullCP = if (si.isManagedVersion) rawCP else si.allJars.toSeq ++ rawCP - val exclude = dependencyJars(exportedProducts).value.toSet ++ si.allJars + val fullCP = if (si.isManagedVersion) rawCP else List(si.libraryJar) ++ rawCP + val exclude = dependencyJars(exportedProducts).value.toSet ++ Set(si.libraryJar) buildLayers( strategy = classLoaderLayeringStrategy.value, si = si,