// Ensure we run outside of sbt. This is especially useful for setting JVM-level flags
fork in run := true
// Set flags for java. Memory, GC settings, properties, etc.
javaOptions ++= Seq("-Xmx4g")
mainClass in run := Some("mypackage.MyMainClass")
That lets you use "run" to spin up a forked JVM with your provided main class and arguments. (Aside: sbt-revolver is a MUCH friendlier way to run main classes).
But what if you want to run a main class with a different set of JVM flags? Maybe you have a memory hog, or you want to specify a debug logback config - or any other number of reasons. Or maybe you just want to have a shortcut for a long class name, or to have a default set of arguments for your main class.
This can be done with the Fork API:
// Create a task for your new main class. This is an input task so that you
// can provide arguments to it via the sbt console.
lazy val runMyOtherMain = inputKey[Unit]("run MyOtherMain")
runMyOtherMain := {
// Parse the arguments typed on the sbt console.
val args = sbt.complete.Parsers.spaceDelimited("[main args]").parsed
// Build up the classpath for the subprocess. Yes, this must be done manually.
// This also ensures that your code will be compiled before you run.
val classpath = (fullClasspath in Compile).value
val classpathString = Path.makeString(classpath map { _.data })
// Any JVM args you want. You could use javaOptions.value to get your default
// list, if you like.
val jvmArgs = Seq("-Xmx4g", "-Dlogback.configurationFile=debug_logback.xml")
Fork.java(
// Full options include whatever you want to add, plus the classpath.
ForkOptions(runJVMOptions = jvmArgs ++ Seq("-classpath", classpathString)),
// You could also add other default arguments here.
"mypackage.MyOtherMainClass" +: args
)
}
Now, you can type runMyOtherMain arg1 arg2 from the sbt console, and it'll execute:
java -Xmx4g -Dlogback.configurationFile=debug_logback.xml -classpath [actual classpath] mypackage.MyOtherMainClass arg1 arg2
Sweet!