Packages

sealed trait ClassLoaderLayeringStrategy extends AnyRef

Represents a ClassLoader layering strategy. By providing an instance of ClassLoaderLayeringStrategy, users can configure the strategy that they want to use in various sbt tasks, most importantly Keys.run and Keys.test. This setting is only relevant if fork := false in the task for which we obtain a ClassLoaderLayeringStrategy.

ClassLoaders can be composed of multiple ClassLoaders to form a graph for loading a class. The different portions of the graph may be cached and reused to minimize both the memory taken up by ClassLoaders (and the classes that they load) and the startup time for tasks like test and run. For example, the scala library is large and takes a while just to load the classes in predef. The Keys.scalaInstance task provides access to a classloader that can load all of the java bootstrap classes and scala.*. Supposing that we want to run code in a jar containing scala code called "foo_2.12.jar" in the base directory and that we have a scala instance in scope and suppose further that "foo_2.12.jar" contains a main method in the class foo.Main, then we can invoke foo.Main.main like so

val fooJarFile = new File("foo_2.12.jar")
val classLoader = new URLClassLoader(
  Array(fooJarFile.toURI.toURL), scalaInstance.loaderLibraryOnly)
val main = classLoader.loadClass("foo.Main").getDeclaredMethod("main", classOf[Array[String]])
main.invoke(null, Array.empty[String])

Now suppose that we have an alternative jar "foo_alt_2.12.jar" that also provides foo.Main, then we can run that main method:

val fooJarFile = new File("foo_alt_2.12.jar")
val altClassLoader = new URLClassLoader(
  Array(fooAltJarFile.toURI.toURL), scalaInstance.loaderLibraryOnly)
val altMain = classLoader.loadClass("foo.Main").getDeclaredMethod("main", classOf[Array[String]])
altMain.invoke(null, Array.empty[String])

In the second invocation, the scala library will have already been loaded by the scalaInstance.loaderLibraryOnly ClassLoader. This can reduce the startup time by O(500ms) and prevents an accumulation of scala related Class objects. Note that these ClassLoaders should only be used at a code boundary such that their loaded classes do not leak outside of the defining scope. This is because the layered class loaders can create mutually incompatible classes. For example, in the example above, suppose that there is a class foo.Bar provided by both "foo_2.12.jar" and "foo_2.12.jar" and that both also provide a static method "foo.Foo$.bar" that returns an instance of foo.Bar, then the following code will not work:

Thread.currentThread.setContextClassLoader(altClassLoader)
val bar: Object = classLoader.loadClass("foo.Foo$").getDeclaredMethod("bar").invoke(null)
val barTyped: foo.Bar = bar.asInstanceOf[foo.Bar]
// throws ClassCastException because the thread context class loader is altClassLoader, but
// but bar was loaded by classLoader.

In general, this should only happen if the user explicitly overrides the thread context ClassLoader or uses reflection to manipulate classes loaded by different loaders.

Source
ClassLoaderLayeringStrategy.scala
Linear Supertypes
AnyRef, Any
Ordering
  1. Alphabetic
  2. By Inheritance
Inherited
  1. ClassLoaderLayeringStrategy
  2. AnyRef
  3. Any
  1. Hide All
  2. Show All
Visibility
  1. Public
  2. All

Value Members

  1. final def !=(arg0: Any): Boolean
    Definition Classes
    AnyRef → Any
  2. final def ##(): Int
    Definition Classes
    AnyRef → Any
  3. final def ==(arg0: Any): Boolean
    Definition Classes
    AnyRef → Any
  4. final def asInstanceOf[T0]: T0
    Definition Classes
    Any
  5. def clone(): AnyRef
    Attributes
    protected[lang]
    Definition Classes
    AnyRef
    Annotations
    @throws( ... ) @native()
  6. final def eq(arg0: AnyRef): Boolean
    Definition Classes
    AnyRef
  7. def equals(arg0: Any): Boolean
    Definition Classes
    AnyRef → Any
  8. def finalize(): Unit
    Attributes
    protected[lang]
    Definition Classes
    AnyRef
    Annotations
    @throws( classOf[java.lang.Throwable] )
  9. final def getClass(): Class[_]
    Definition Classes
    AnyRef → Any
    Annotations
    @native()
  10. def hashCode(): Int
    Definition Classes
    AnyRef → Any
    Annotations
    @native()
  11. final def isInstanceOf[T0]: Boolean
    Definition Classes
    Any
  12. final def ne(arg0: AnyRef): Boolean
    Definition Classes
    AnyRef
  13. final def notify(): Unit
    Definition Classes
    AnyRef
    Annotations
    @native()
  14. final def notifyAll(): Unit
    Definition Classes
    AnyRef
    Annotations
    @native()
  15. final def synchronized[T0](arg0: ⇒ T0): T0
    Definition Classes
    AnyRef
  16. def toString(): String
    Definition Classes
    AnyRef → Any
  17. final def wait(): Unit
    Definition Classes
    AnyRef
    Annotations
    @throws( ... )
  18. final def wait(arg0: Long, arg1: Int): Unit
    Definition Classes
    AnyRef
    Annotations
    @throws( ... )
  19. final def wait(arg0: Long): Unit
    Definition Classes
    AnyRef
    Annotations
    @throws( ... ) @native()

Inherited from AnyRef

Inherited from Any

Ungrouped