Fat Jar Eclipse Plug-In Frequently Asked Questions (FAQ)


Question 1: I Have a project which uses SWT. After building the Fat-Jar it does not start

I assume you are missing the SWT-DLL (swt-win32.dll) which is needed by swt.jar. This DLL is used by JNI (Java Native Interface) which uses platform-specific native code. So there is no way to store the DLL inside the jar, because windows does not handle DLLs in ZIP Files.

The Virtual Machine needs to know where to search for this DLL, so the folder containing the DLL must be passed to the VM like this: "java -Djava.library.path=path\to\swt\dlls -jar myfat.jar"

If the DLL is in the same directory as the jar file, then it is found without any vm-parameters. So if you deliver your application for example on a CD, then just put the swt.dll into the same folder as the jar file and all should work fine (of course platform-specific).

another possibility is to store the dll as a resource into the jar and extract it when the application is first started. I have attached another mail and eclipse-project showing this solution:

An example project can be downloaded here: test-main_SWT.zip
It was build for windows with Eclipse 3.0.1

How to build in short:

The Application just opens a window with a label "hello world".
The first run an exception is printed (for debugging info) which can be ignored.
swt.dll is extracted into the current working directory, so no java.library.path has to be set.

source:
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;

import org.eclipse.swt.SWT;
import org.eclipse.swt.internal.Library;
import org.eclipse.swt.layout.RowLayout;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;

public class TestMainSWT {

    static {
        System.out.println("first");
        preprocessSWT();
    }
    // -Djava.library.path=U:\opt\eclipse301\plugins\org.eclipse.swt.win32_3.0.1\os\win32\x86

    private static void preprocessSWT() {
        String filename = null;
        try {
            System.out.println("new Label()");
            Library.loadLibrary("swt");
        }
        catch (IllegalArgumentException ignore) {}
        catch (Throwable e) {
            e.printStackTrace();
            filename = e.getMessage().replaceAll("no ([-_a-zA-Z0-9]+) in java.library.path", "$1");
            filename += ".dll";
        }
        try {
            System.out.println(filename);
            if (filename != null) {
                URL swtdllurl = Thread.currentThread().getContextClassLoader().getResource("swt-win32-3063.dll");
                InputStream is = swtdllurl.openStream();
                OutputStream os = new FileOutputStream("swt-win32-3063.dll");
                byte[] buf = new byte[4096];
                int cnt = is.read(buf);
                while (cnt > 0) {
                    os.write(buf, 0, cnt);
                    cnt = is.read(buf);
                }
                os.close();
                is.close();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    
    public static void main(String[] args) {

        System.out.println("main");
        Display display = new Display();
        Shell shell = new Shell(display);
        shell.setLayout( new RowLayout());

        // ------------------------
        // Your code comes to here.
        // ------------------------
        Label label = new Label(shell, SWT.NORMAL);
        label.setText("Hello World!");
        
        shell.pack();
        shell.open();
        while( !shell.isDisposed()) {
            if(!display.readAndDispatch()) 
                display.sleep();
        }
        display.dispose();
    }
    
}

back