The sbt launcher is a mechanism whereby modules can be loaded from Ivy and executed within a JVM. It abstracts the mechanism of grabbing and caching jars, allowing users to focus on what application they want, and control its versions.
The launcher’s primary goal is to take configuration for applications— mostly Ivy coordinates and a main class—and start the application. The launcher resolves the Ivy module, caches the required runtime jars, and starts the application.
The sbt launcher provides the application with the means to load a different application when it completes, exit normally, or load additional applications from inside another.
The sbt launcher provides these core functions:
The primary purpose of the sbt launcher is to resolve applications and
run them. This is done through the [app]
configuration section. See
[launcher configuration][Launcher-Configuration] for more information on how to configure module
resolution.
Module resolution is performed using the Ivy dependency management library. This library supports loading artifacts from Maven repositories as well.
The sbt launcher’s classloading structure is different than just
starting an application in the standard Java mechanism. Every
application loaded by the launcher is given its own classloader. This
classloader is a child of the Scala classloader used by the application.
The Scala classloader can see all of the xsbti.*
classes from the
launcher itself.
Here’s an example classloader layout from an sbt-launched application.
In this diagram, three different applications were loaded. Two of these use the same version of Scala (2.9.2). In this case, sbt can share the same classloader for these applications. This has the benefit that any JIT optimisations performed on Scala classes can be re-used between applications thanks to the shared classloader.
The sbt launcher creates a secondary cache on top of Ivy’s own cache.
This helps isolate applications from errors resulting from unstable
revisions, like -SNAPSHOT
. For any launched application, the launcher
creates a directory to store all its jars. Here’s an example layout.
In addition to providing a secondary cache, the launcher also provides a mechanism of safely doing file-based locks. This is used in two places directly by the launcher:
This feature requires a filesystem which supports locking. It is exposed
via the xsbti.GlobalLock
interface.
The launcher also provides a mechanism to ensure that only one instance
of a server is running, while dynamically starting it when a client
requests. This is done through the --locate
flag on the launcher. When
the launcher is started with the --locate
flag it will do the
following:
The configured server.lock
file is thus used to prevent multiple
servers from running. sbt itself uses this to prevent more than one
server running on any given project directory by configuring
server.lock
to be ${user.dir}/.sbtserver
.