Explanation of library/build files/jars, setting up Slick2D

Greetings. I have a threefold question. Technically, I have one problem, but I would like an explanation as to how java mechanics work as related to libraries.

It seems to me that most such questions are how to make something work, but not why it works. But in this case, you do not learn how it works, either, and I would like to know this, not just a quick fix.

My first question is this: many libraries are either in whole or in part, a jar, or several jars. As I understand it, you set the classpath, not to the directory the jar is in, but the jar itself. IS this accurate, and if so, why? (mechanics of class loading, if possible). Is this because a .jar is essentially a folder (albeit zipped), and so this is accurate in terms of file structure?

Second, external dependancies. Those libraries need to use DLLs. I don’t need to know how JNI/JNA works at this time, but I am unsure what needs to be done in terms of adding these to classpath or other build paths. What do you do and why?

Finally - I am trying to use Slick2D. I have a classpath set for the jar, and no errors come from there, but I got errors from LWJGL. I linked to those jars, and not get another error,

java.lang.UnsatisfiedLinkError: no lwjgl in java.library.path

How do I fix this, and why?

Read the part about natives

There are two kinds of paths to know: the classpath and the java.library.path.

The classpath contains all Java bytecode: *.class files, either standalone or in *.jar files (JAR files are actually ZIP files that contains *.class btw). For this it is generally best to list the JARs individually.

The “library path” is for native files that you want the JVM to be able to find. It is best to just reference a single folder that contains the natives. For example with LWJGL, make a folder that contains the Windows “lwjgl.dll” and “lwjgl64.dll”, Linux “liblwjgl.so” and “liblwjgl64.so”, and Mac “liblwjgl.jnilib” files (all the other natives don’t need to be included if you don’t use OpenAL and/or JInput for your application. Of course they have to be added if you want to use them.)

For your error, the problem is simply that you don’t have the LWJGL natives in the library path. If you are using Eclipse, check out the LWJGL wiki. If you are attempting to export the JARs by themselves, check out HeroesGraveDev’s link. I wrote most of the article he linked so if you need clarification, feel free to ask!

By command line, it would be:


java -classpath "path/to/MyJar.jar;another/path/to/AnotherJar.jar" -Djava.library.path="path/to/natives_folder/" com.mypackage.MyMainClass

The hidden switch method in HeroesGraveDev’s link is my favorite. It seems a lot easier than making a launch script.

For example, these are the two lines I use to set up my Pixel Zombies game via Slick2d (setting up LWJGL is the first line):


System.setProperty("org.lwjgl.librarypath", new File(new File(System.getProperty("user.dir"), "native"), LWJGLUtil.getPlatformName()).getAbsolutePath());
System.setProperty("net.java.games.input.librarypath", System.getProperty("org.lwjgl.librarypath"));

Thanks for the replies, and sorry this is a bit late. I am a bit confused, though.

First, I would would say a jar is sort of like a normal folder. Does setting the classpath to the file of the jar rather than the directory reflect this?

Second, when deploying applications, how do you make it work for them classpath wise?

Third, on the local paths - same as above, how you you make it work for the user?

Fourth, on the local paths, is it sort of like the classpath, but is a relative point for loading DLLS? By this, I mean, say, you have a folder,natives. When you make a call such as the the system ones below, it looks for them starting from that point?

Fifth, what does System.setProperty do?

Sixth, I don’t use Eclipse, but rather Dr Java, which os unfortunate considering all advice seems to be for Eclipse. There is a build path, but I am not sure if this is the same or different… does it need to be set outside, in code, or either way?

Ah I forgot that you can just use getAbsolutePath() with File! With that, there is no need to use the “user.dir” property (I’ve heard it’s unreliable too).


System.setProperty("org.lwjgl.librarypath", new File("natives").getAbsolutePath());

I’ll update the article.

  1. A JAR is a ZIP file. In the classpath, you list all the JARs used by your application, as shown by my earlier post.

  2. What do you mean? Again, look at my earlier post.

  3. “local paths”?

  4. “java.library.path” is where you point to your folder of natives.

  5. System has a Map that maps Strings to Strings which is used to set properties and settings. It does nothing more than associate a String with another String. In this example, you do System.setProperty(“org.lwjgl.librarypath”, new File(“natives”).getAbsolutePath()) and that associates whatever String getAbsolutePath() returns with “org.lwjgl.librarypath”. Then in LWJGL’s initializing code, it does System.getProperty(“org.lwjgl.librarypath”) to see if there is a String associated with it, and if there is, it loads the natives from there.

  6. With most IDE’s, it takes care of things like the classpath for you so you will need to check with its documentation to figure it out.

  1. Well, I could set the classpaths during development, but they don’t exists without the IDE on another computer, so I was wondering how that is specified.

  2. Same as above, but in terms of paths to native DLLS and such, especially if you package it all in a jar.

  3. What I meant was, in terms of normally loading DLLS using JNI/JNA, what path needs to be set and to what - a directory of DLLS, for example, or to a DLL itself.

Yes, you are correct, listing jars and folders containing their content is equivalent. The directory structure in the folder or jar should match the package structure. The jars/folders in the classpath should contain the .class files, which are the build results of compiling .java files.

You either specify the list of jars/folders in the -classpath or -cp commandline argument like ra4king already pointed out, or you build your jar in a way that it is executable with java -jar (and by double clicking them - but this is often broken due to programs like WinZip grabbing the .jar extension :/). To do so, you have to specify the library jars relative to your main jar in the manifest.mf attribute “Class-Path:” (see http://docs.oracle.com/javase/tutorial/deployment/jar/downman.html)

I assume you mean the java.library.path? The java.library.path contains a list of folders containing your applications native libraries (.dll files on windows .so files on linux). The java.library.path is set as a system property using the -D commandline option. This usually only works from the commandline and not from inside of java code, so some libraries introduced a workaround like the hidden system property of LWJGL.

System.setProperty sets a system-property and is more or less equivalent with passing a -D option to the java call on the commandline. A system-property is javas equivalent to environment variables. You can use them to set and query global informations of the current java process.

From looking at the DrJava documentation (http://www.drjava.org/docs/user/ch04s03.html), the Build-Directory will contain the compiled classes and the Extra-Classpath can be used to specify libraries. I can’t see any option for passing system properties, so you might either use the LWJGL specific [icode]System.setProperty(“org.lwjgl.librarypath”,…)[/icode], or switch to a real IDE (highly recommended - I like Intellij Idea best…)

You usually create two script files containing the necessary java commandline options. A .bat file for windows and a .sh file for linux/mac. There are some third party solutions out there that can wrap your java application in an exe file or a mac native.

Unfortunately you can’t simply package natives in a jar. All solutions that do that, silently unpack the jar to some temp folder and set the oppropriate system property to the location they were unpacked. Other than that, same answer as above - include the neccessary -D option to the java call in your wrapper-script.

In contrast to the classparth, the java.library.path has to point to the folder where the DLLs are in, not to the DLLs itself.