Speed: Windows >>> OS X? Am I missing something?

Started by directedchaos, August 31, 2007, 02:35:27

Previous topic - Next topic

directedchaos

Thank you for the explanation!  I gather I'm facing two problems:

  • Forcing lwjgl to try to load the local bundled openal before the system openal.  (though the problem probably isn't specific to openal)
  • My machine running OS X won't load openal.dylib, even when trying the exact absolute pathname to the file.
In the first case, should I mess with a custom class loader to override findLibrary, immediately returning the local path?  If I could do this, it would mean I could also move the natives to a more discreet location instead of floating in the main folder.  I've been doing some experimenting and can't seem to get it to use my custom class loader.  I've tried both setting the thread and system classloader.

Here's the simple classloader, just for testing:
public class FF_lwjgl_ClassLoader extends ClassLoader{
    public FF_lwjgl_ClassLoader(ClassLoader parent){
        super(parent);
    }
    public FF_lwjgl_ClassLoader(){ ; }
    public String findLibrary(String libName){
        String s = super.findLibrary(libName);

        System.out.println("findLibrary("+libName+") called value: '"+s+"'");
        return s;
    }
}


Here's how I set the thread:
FF_lwjgl_ClassLoader loader = new FF_lwjgl_ClassLoader(Thread.currentThread().getContextClassLoader());
Thread.currentThread().setContextClassLoader(loader);

And for the system I added -Djava.system.class.loader=futilefantasy.FF_lwjgl_ClassLoader to the command-line arguments (futilefantasy is the package name; the class is found just fine, no errors)

The output was unchanged, implying that I'm not actually accessing AL's classloader.  I gather this section from AL.java is where the action happens:
String[] oalPaths = LWJGLUtil.getLibraryPaths(libname, library_names, AL.class.getClassLoader())

Somehow, I have to make sure AL.class.getClassLoader() returns my custom class loader.

As a side note, the "failed to locate findLibrary method" errors are no biggy, as it searches up the inheritance chain until findLibrary is defined?

Somehow, I think this isn't what most people do when they bundle lwjgl with their game desktop-side.  Ideas, anyone?


The second problem might be more daunting though.  Again, it tries the exact absolute path to openal.dylib:
Testing '/Projects/Java/Futile Fantasy/FF_latest_build/openal.dylib'
Failed to load /Projects/Java/Futile Fantasy/FF_latest_build/openal.dylib: Could not load OpenAL library

and fails.  I'm clueless.  :(

elias

Putting the library beside the lwjgl library should work, since lwjgl also tries to locate openal by locating the main lwjgl native library (liblwjgl.jnilib), then cutting out the liblwjgl.jnilib part and replacing it with openal.dylib.

The failure to find method errors are not a problem.

Failing to load openal.dylib is probably caused by us using a ppc-compiled openal.dylib and you running an intel mac. The bundled openal.dylib won't work on intel macs. The reason behind this is that all intel macs have at least mac os x 10.4 where openal is built in, thus only requiring the bundled openal library for ppc macs. liblwjgl.jnilib is special, since it is compiled to work on both 10.3 ppc and 10.4 intel machines. Theortically, the same could be done to openal.dylib, but I haven't yet bothered to fiddle with the openal build scripts (it involves compiling the entire library with two different compilers, then using a special tool to glue the parts together).

- elias

directedchaos

Thanks again!  I understand this is all done in donated free time, and I appreciate the library -- I wouldn't be able to make this game without openGL bindings (I tried, too many rotations -- needed hardware acceleration).  You've been very helpful!

I do have an intel mac, and the sounds are fine (in fact, my entire game works wonderfully on my machine -- minus my poor artistic abilities).  The potentially dangerous scenario I'm trying to avoid is where lwjgl checks the system's openal library (say, under 'C:\WINDOWS\system32\OpenAL32.dll') first, finds it, and uses it without ever checking the local bundled lwjgl openal. It seems like this is something the default classloader does.

elias

Right, so does it work when you put the bundled openal library in the same directory as the lwjgl native library? That should always be tried first by AL, and only the system library path last.

directedchaos

Yes, all the native files are in the same folder -- the folder that the game itself is in.  If I don't set -Djava.library.path, lwjgl checks the system openal first:

Found 10 OpenAL paths
Testing 'C:\WINDOWS\system32\OpenAL32.dll'
Failed to load C:\WINDOWS\system32\OpenAL32.dll: Could not load OpenAL library
Testing '.\OpenAL32.dll'
Found OpenAL at '.\OpenAL32.dll'


(I just happen to not have a system openal, so it works fine on mine)

If I do set -Djava.library.path (to the absolute path to the game directory), it finds it on the first go as the absolute path to the bundled openal:
Found 3 OpenAL paths
Testing 'C:\[...]\FF_latest_build\OpenAL32.dll'
Found OpenAL at 'C:\[...]\FF_latest_build\OpenAL32.dll'


So, is the prevailing solution just to write custom OS-specific launch scripts?  I was trying to avoid that with the JAR.

elias

Scripts or a custom classloader will solve it. If you use a custom classloader, you can't use the one you posted earlier in this thread. To make it work, you have to make sure your custom classloader actually loads the LWJGL classes, not the parent class loader. FF_lwjgl_ClassLoader always delegates to its parent (because that's the default implementation of ClassLoader.loadClass), and thus AL.class.getClassLoader() will be the parent class loader. You can probably make it work, but it requires some fiddling (for example, let FF_lwjgl_ClassLoader inherit from URLClassLoader with your jar as the classpath). You can always test if it works by querying AL.class.getClassLoader() and see if it is your classloader or something else.

- elias