Embedding and loading a JNI library from a jar

When I searched for ways to load a JNI library from a jar there were numerous hints of how to do it, but no code that I could find. So here’s my solution:

import java.net.URL;
import java.util.zip.ZipFile;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;

public abstract class UnixDomainSocket {

    static {
        try {
            // get the class object for this class, and get the location of it
            final Class c = UnixDomainSocket.class;
            final URL location = c.getProtectionDomain().getCodeSource().getLocation();
            
            // jars are just zip files, get the input stream for the lib
            ZipFile zf = new ZipFile(location.getPath());
            InputStream in = zf.getInputStream(zf.getEntry("libunixdomainsocket.jnilib"));
            
            // create a temp file and an input stream for it
            File f = File.createTempFile("JARLIB-", "-libunixdomainsocket.jnilib");
            FileOutputStream out = new FileOutputStream(f);
            
            // copy the lib to the temp file
            byte[] buf = new byte[1024];
            int len;
            while ((len = in.read(buf)) > 0)
                out.write(buf, 0, len);
            in.close();
            out.close();
    
            // load the lib specified by it’s absolute path and delete it
            System.load(f.getAbsolutePath());
            f.delete();
            
        } catch (Exception e) {
            e.printStackTrace();
            System.exit(1);
        }
    }
    
    // …
}

This particular example is for JUDS.

It could be extended to load one of several libraries for different architectures, .jnilib or .dylib for Mac OS X, .so for Linux, and .dll for Windows.

This seems like a lot of hoops to jump through, but I couldn’t find an easier way to do it. If you know of a better way, please let me know in the comments.

  • DataFiddler

    Nice, thanks.
    Google correctly rates this entry very high πŸ˜‰
    I think I manage to add an automatic switch between .dll and .so depending on the current platform myself …

  • Ein Staunender

    Do you know JNA? It’s much easier as to use JNI directly.

  • Matthieu

    Very nice, thank you.

    Is it possible when the JAR is loaded by an applet ?

    The location : “location = c.getProtectionDomain().getCodeSource().getLocation();” becomes not good.

    Thank you for the response.

    Matthieu