LWJGL Forum
Programming => Lightweight Java Gaming Library => Topic started by: mstWeal on September 12, 2010, 18:56:07
-
Hi there,
how does LWJGL determine when to load the 64bit DLLs and when to load the 32bit DLLs?
For I have a 64bit system. So far everything worked fine but I started to use PowerMock to write my unit tests. Curiously, if I start unit tests with the PowerMock test runner there is an unsatisfied exception, stating that 32bit DLLs cannot be loaded on AMD 64 bit processors. I removed the 32bit DLLs but then it complains that lwjgl.dll cannot be found ...
-
Sys.java:
private static void loadLibrary(final String lib_name) {
try {
doLoadLibrary(lib_name);
} catch (UnsatisfiedLinkError e) {
if (implementation.has64Bit()) {
try {
doLoadLibrary(lib_name + POSTFIX64BIT);
return;
} catch (UnsatisfiedLinkError e2) {
LWJGLUtil.log("Failed to load 64 bit library: " + e2.getMessage());
}
}
// Throw original error
throw e;
}
}
one could argue that if 64 bit is available for the implementation it would try that first.
something similar to this:
private static void loadLibrary(final String lib_name) {
if (implementation.has64Bit()) {
try {
doLoadLibrary(lib_name + POSTFIX64BIT);
return;
} catch (UnsatisfiedLinkError e2) {
LWJGLUtil.log("Failed to load 64 bit library: " + e2.getMessage());
}
}
try {
doLoadLibrary(lib_name);
} catch (UnsatisfiedLinkError e) {
// Throw original error
throw e;
}
}
-
Okay thank you. I've debugged into that code and the source of the exception says the following:
"Native Library E:\Dokumente\Workspace\lib\lwjgl\native\windows\lwjgl64.dll already loaded in another classloader"
Well that explains why the test works if I only run the PowerMock test alone but not when I run all my tests together. PowerMock uses it's own class loader and then this leads to this situation. Is it possible to "fix" this at LWJGL level?
-
I dont think we'd want to support this on a lwjgl level - not sure...
however the appletload has an 'unloadNatives' method that kappa added to fix this issue for applet. You may be able to use this.
/**
* Unload natives loaded by a different classloader.
*
* Due to limitations of the jvm, native files can only
* be loaded once and only be used by the classloader
* they were loaded from.
*
* Due to the way applets on plugin1 work, one jvm must
* be used for all applets. We need to use multiple
* classloaders in the same jvm due to LWJGL's static
* nature. I order to solve this we simply remove the
* natives from a previous classloader allowing a new
* classloader to use those natives in the same jvm.
*
* This method will only attempt to unload natives from a
* previous classloader if it detects that the natives have
* been loaded in the same jvm.
*
* @param nativePath directory where natives are stored
*/
private void unloadNatives(String nativePath) {
// check whether natives have been loaded into this jvm
if (!natives_loaded) {
return;
}
try {
Field field = ClassLoader.class.getDeclaredField("loadedLibraryNames");
field.setAccessible(true);
Vector libs = (Vector) field.get(getClass().getClassLoader());
String path = new File(nativePath).getCanonicalPath();
for (int i = 0; i < libs.size(); i++) {
String s = (String) libs.get(i);
// if a native from the nativePath directory is loaded, unload it
if (s.startsWith(path)) {
libs.remove(i);
i--;
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
-
Thank you, this should workaround the problem for me as I will be able to unload the libraries in the tearDown method of the test cases :-)