For a while now I kept thinking how I would create an executable jar that would contain the Scala runtime. Tonight, I decided to give it a shot and try to make it work.
If you don’t already know, a jar is nothing but a zip file that includes a manifest ( which holds some information ).
To test this, I used the following code:
import java.io._
object Whatever
{
def main(args:Array[String]) = {
new File(args(0)).listFiles.foreach(println)
}
}
So … first we compile it to bytecode. We use scalac for that:
scalac x.scala
If you’re using the code I posted above, you should get 3 classes out of the compilation process. Next, we need to create a manifest:
Main-Class: Whatever
Please notice there is an extra line after the line with Main-Class.
Now, we need to actually create the jar. We use the jar binary that ships with your Java installation:
jar -cvfm h.jar Manifest.mf Whatever.class Whatever$$anonfun$main$1.class Whatever.class Whatever$.class
Ok, so if we now run the existing h.jar jar, you should get this exception:
Exception in thread "main" java.lang.NoClassDefFoundError: scala/ScalaObject
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClassCond(ClassLoader.java:632)
at java.lang.ClassLoader.defineClass(ClassLoader.java:616)
at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:14
1)
at java.net.URLClassLoader.defineClass(URLClassLoader.java:283)
at java.net.URLClassLoader.access$000(URLClassLoader.java:58)
at java.net.URLClassLoader$1.run(URLClassLoader.java:197)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
at java.lang.ClassLoader.loadClass(ClassLoader.java:307)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
at java.lang.ClassLoader.loadClass(ClassLoader.java:248)
at Whatever.main(x.scala)
Caused by: java.lang.ClassNotFoundException: scala.ScalaObject
at java.net.URLClassLoader$1.run(URLClassLoader.java:202)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
at java.lang.ClassLoader.loadClass(ClassLoader.java:307)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
at java.lang.ClassLoader.loadClass(ClassLoader.java:248)
... 13 more
It’s because it can’t find the Scala runtime. So … here comes the “not so elegant way” of adding the Scala runtime
. In your Scala’s installation folder, you have a folder named lib which contains a jar named scala-library.jar. I’m assuming you have some software that can extract zip archives ( I think most operating systems have this by default ). Extract that archive to some directory, and notice the scala folder. Now, open the jar we created above using your favourite compression software. You should have the following structure:

Remember the scala package I told you about a couple of lines above? Simply drag it into your archive, at the same level as the META-INF folder, like in the following picture:

After this is over, you can try to run your jar again:
java -jar h.jar .
And it should/will work. In a day or two, I’ll show you how to accomplish the same thing using jarjar.