Archive for the 'jar' Category

31
Jan
10

the not so elegant way of creating an executable jar from scala code


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.

24
Jan
10

finding out which jar a class comes from


If you ever need to know from what jar file a class originates, this line can help you:


 System.out.println(SomeClass.class.getProtectionDomain().
                getCodeSource().getLocation());




Blog Stats

  • 215,259 hits