I am using DJ and I am displaying the native file dialogs. To display these, it needs a library specific to the OS. The library has some dll files as well as some classes. I would like to load the specific library (Windows, Linux, or Mac) depending on the OS it is running. I tried System.load()
but it appears that this loads just the dll files and not a jar with them and other classes as I get this error.
System.load(System.getProperty("user.dir")+"/binaries/lib/swt-win64.jar");
Exception in thread "main" java.lang.UnsatisfiedLinkError: E:\Eclipse\workspace\PinewoodDerby\binaries\lib\swt-win64.jar: Can't load this .dll (machine code=0x4ba4) on a AMD 64-bit platform
at java.lang.ClassLoader$NativeLibrary.load(Native Method)
at java.lang.ClassLoader.loadLibrary1(Unknown Source)
at java.lang.ClassLoader.loadLibrary0(Unknown Source)
at java.lang.ClassLoader.loadLibrary(Unknown Source)
at java.lang.Runtime.load0(Unknown Source)
at java.lang.System.load(Unknown Source)
at derby.DerbyProgram.<init>(DerbyProgram.java:144)
at derby.DerbyProgram.getInstance(DerbyProgram.java:119)
at derby.DerbyProgram.main(DerbyProgram.java:110)
I downloaded the jar from Eclipse's website and just extracted swt.jar
and renamed it to swt-win64.jar
Everything works fine if I include swt-win64.jar
in my class path but this means that this build only works for 64-bit Windows and nothing else, I would like the same jar to work on all platforms.
UPDATE: When I load the swt jar with the code from this post, I get this exception:
Exception in thread "main" java.lang.NoClassDefFoundError: org/eclipse/swt/SWT
at chrriis.dj.nativeswing.swtimpl.core.SWTNativeInterface.initialize_(SWTNativeInterface.java:213)
at chrriis.dj.nativeswing.swtimpl.NativeInterface.initialize(NativeInterface.java:71)
at chrriis.dj.nativeswing.swtimpl.core.SWTNativeInterface.open_(SWTNativeInterface.java:337)
at chrriis.dj.nativeswing.swtimpl.NativeInterface.open(NativeInterface.java:100)
at derby.DerbyProgram.<init>(DerbyProgram.java:161)
at derby.DerbyProgram.getInstance(DerbyProgram.java:130)
at derby.DerbyProgram.main(DerbyProgram.java:121)
Caused by: java.lang.ClassNotFoundException: org.eclipse.swt.SWT
at java.net.URLClassLoader$1.run(URLClassLoader.java:372)
at java.net.URLClassLoader$1.run(URLClassLoader.java:361)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:360)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
... 7 more
I read over the code, addUrlMethod.invoke(classLoader, swtFileUrl)
the method we are using here, addURL
this seems that we are adding a URL and not actually loading the classes. I launched my program with the -verbose
argument and it didn't say anything about loading the SWT. This is my current code for loading the classes:
private void loadSWTJar() throws MalformedURLException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException {
String osName = System.getProperty("os.name").toLowerCase();
String osArch = System.getProperty("os.arch").toLowerCase();
URLClassLoader classLoader = (URLClassLoader) getClass().getClassLoader();
Method addUrlMethod = URLClassLoader.class.getDeclaredMethod("addURL", URL.class);
addUrlMethod.setAccessible(true);
String swtFileNameOsPart = osName.contains("win") ? "win" : osName.contains("mac") ? "maco" : osName.contains("linux") || osName.contains("nix") ? "linux" : ""; // throw new RuntimeException("Unknown OS name: "+osName)
String swtFileNameArchPart = osArch.contains("64") ? "64" : "32";
String swtFileName = "swt-" + swtFileNameOsPart + "-" + swtFileNameArchPart + ".jar";
URL swtFileUrl = new URL("file:" + System.getProperty("user.dir") + "/lib/"+swtFileName);
System.out.println(addUrlMethod.invoke(classLoader, swtFileUrl));
System.out.println("Loaded SWT jar: " + swtFileUrl);
}
UPDATE 2: I got this code working but it only works on a Windows machine. I do not receive any error on Windows but I get the same error:
Exception in thread "main" java.lang.NoClassDefFoundError: org/eclipse/swt/SWT
Here is my new code:
private String getSwtJarName() throws OSNotDetectedException {
String swtFileName = "swt-" + getOS() + ".jar"; //$NON-NLS-1$ //$NON-NLS-2$
return swtFileName;
}
private String getOS() throws OSNotDetectedException {
String osName = System.getProperty("os.name").toLowerCase(); //$NON-NLS-1$
String os = osName.contains("win") ? "win" : osName.contains("mac") ? "mac" : osName.contains("linux") || osName.contains("nix") ? "linux" : ""; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$
if ("".equals(os)) { //$NON-NLS-1$
throw new OSNotDetectedException();
}
return os + "-" + getArch(); //$NON-NLS-1$
}
class OSNotDetectedException extends Exception{
private static final long serialVersionUID = 1L;
OSNotDetectedException(){}
OSNotDetectedException(Throwable e){
super(e);
}
}
private String getArch() {
String jvmArch = System.getProperty("os.arch").toLowerCase(); //$NON-NLS-1$
String arch = jvmArch.contains("64") ? "64" : "32"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
return arch;
}
private void loadSWT() throws IOException, NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, OSNotDetectedException {
String prefix;
if (debugMode) {
prefix = "binaries/lib"; //$NON-NLS-1$
} else {
prefix = "lib"; //$NON-NLS-1$
}
String swtJarName = prefix + "/" + getSwtJarName(); //$NON-NLS-1$
System.out.println("Loading SWT:"); //$NON-NLS-1$
System.out.println(swtJarName);
addFile(swtJarName);
try {
NativeInterface.open();
}
catch (NoClassDefFoundError e) {
throw new OSNotDetectedException(e);
}
}
private static void addFile(String s) throws IOException, NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
File f = new File(s);
addFile(f);
}
private static void addFile(File f) throws IOException, NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
addURL(f.toURI().toURL());
}
private static void addURL(URL u) throws IOException, NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
URLClassLoader sysloader = (URLClassLoader) ClassLoader.getSystemClassLoader();
Class<URLClassLoader> sysclass = URLClassLoader.class;
@SuppressWarnings("rawtypes")
Class[] parameters = new Class[] { URL.class };
Method method = sysclass.getDeclaredMethod("addURL", parameters); //$NON-NLS-1$
method.setAccessible(true);
method.invoke(sysloader, new Object[] { u });
}