Linking to JOGL natives Libraries programatically

I’m trying to set the path to find the JOGL native libraries by setting the java.library.path property using System.setProperty . The program does change the property (i.e. System.getProperty after has the appropriate location appended to the path), but when I make calls to JOGL that should generate OpenGL Contexts, I get the exception described below . Note that this is different from the UnsatisfiedLinkError that is thrown if I don’t set the path… do I have to re-initialize the class or something? And of course, it works fine if I actually put the libraries in the appropriate spot for my OS.

Exception occurred during event dispatching:
java.lang.NoClassDefFoundError
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:164)
at javax.media.opengl.GLDrawableFactory.getFactory(GLDrawableFactory.java:106)
at javax.media.opengl.GLCanvas.(GLCanvas.java:113)
at net.java.joglutils.GLJFrame.initComponents(GLJFrame.java:187)
at net.java.joglutils.GLJFrame.(GLJFrame.java:92)
at net.java.joglutils.GLJFrame.(GLJFrame.java:115)
at sddm.Launcher.launchModule(Launcher.java:704)
at sddm.Launcher.launchModule(Launcher.java:806)
at sddm.Launcher.okButtonActionPerformed(Launcher.java:250)
at sddm.Launcher.okButtonActionPerformed(Launcher.java:273)
at sddm.Launcher.access$000(Launcher.java:25)
at sddm.Launcher$1.actionPerformed(Launcher.java:72)
at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:1849)
at javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2169)
at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:420)
at javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:258)
at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.java:234)
at java.awt.Component.processMouseEvent(Component.java:5488)
at javax.swing.JComponent.processMouseEvent(JComponent.java:3126)
at java.awt.Component.processEvent(Component.java:5253)
at java.awt.Container.processEvent(Container.java:1966)
at java.awt.Component.dispatchEventImpl(Component.java:3955)
at java.awt.Container.dispatchEventImpl(Container.java:2024)
at java.awt.Component.dispatchEvent(Component.java:3803)
at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4212)
at java.awt.LightweightDispatcher.processMouseEvent(Container.java:3892)
at java.awt.LightweightDispatcher.dispatchEvent(Container.java:3822)
at java.awt.Container.dispatchEventImpl(Container.java:2010)
at java.awt.Window.dispatchEventImpl(Window.java:1774)
at java.awt.Component.dispatchEvent(Component.java:3803)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:463)
at java.awt.EventDispatchThread.pumpOneEventForHierarchy(EventDispatchThread.java:242)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:163)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:153)
at java.awt.Dialog$1.run(Dialog.java:515)
at java.awt.Dialog.show(Dialog.java:536)
at java.awt.Component.show(Component.java:1300)
at java.awt.Component.setVisible(Component.java:1253)
at sddm.Launcher.showWindow(Launcher.java:967)
at sddm.Launcher$7.run(Launcher.java:419)
at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:209)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:461)
at java.awt.EventDispatchThread.pumpOneEventForHierarchy(EventDispatchThread.java:242)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:163)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:157)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:149)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:110)

I believe java.library.path is parsed very early during bootstrapping and changing it with System.setProperty() has no effect. If you need to set up the library search path yourself you’ll need to use System.load() instead of System.loadLibrary(). Take a look at the source code for the JOGLAppletLauncher for some hints in this area.

I tried System.load on all the JOGL libraries, but I got the exact same NoClassDefFoundError …
Actually, when I called load before launching JOGL objects, it still gave anInsatisfiedLinkError, and when I called load as the step immediately before working with JOGL, it gave the NoClassDefFoundError… But when I look at the error message, it says “no jogl in java.library.path” , so I presume the issue there is that JOGL calls loadLibrary… but still, the load methods don’t seem to help.

Please look at the source code for the JOGLAppletLauncher. It uses the internal NativeLibLoader class to stop the core JOGL code from calling System.loadLibrary() because it does this work itself. You should also double-check to make sure you haven’t dropped either a jogl.jar or the JOGL native library in to your JDK, but instead refer to them via CLASSPATH or some other mechanism. If you put jogl.jar into jre/lib/ext then you are going to have severe problems trying to load up the native libraries.

I modeled the code after the JOGLAppletLauncher, but I didn’t notice the com.sun.opengl.impl.NativeLibLoader.disableLoading(); line the first time around. At any rate, with that in, it works if I provide the libraries to load at launch (before trying to do JOGL work), but I prefer to prompt the user for libraries only if launching fails (i.e. if the UnsatisfiedLinkError is thrown when I try to launch the JOGL rendering). If I do that, it throws the NoClassDefFoundError. It looks to me like this error is basically that the com.sun.opengl.impl.windows.WindowsGLDrawableFactory static initializer throws an error (that I catch) but is hence not loaded correctly… so how do I convince JOGL to try to re-initialize the current factory?

Of course, I could just get around this by manually loading the libraries when the application starts no matter what… but I’d rather not have to do that if the libraries actually are in the appropriate (platform-specific) locations.

I think you may be out of luck. I suspect that the UnsatisfiedLinkError being thrown during the initialization of the factory may be causing the JVM to treat the class as being in an “error” state and preventing subsequent access to it. You may be able to play some games with the NativeLibLoader’s closure-based library loading system contributed by user s_koehler.

If you want to set the java.library.path after the JVM has been loaded you can use the code below which resets sys_path field so that it gets loaded again after you have changed the java.library.path system property.

`
/**
*
*/
public static void addLibraryPath(String path)
{
Class sysclass = ClassLoader.class;

try
{
  String oldPath = System.getProperty("java.library.path");

  Field field = sysclass.getDeclaredField("sys_paths");
  boolean accessible = field.isAccessible();
  if (!accessible)
    field.setAccessible(true);
  Object original = field.get(sysclass);
  /* Reset it to null so that whenever "System.loadLibrary" is
   * called it will be reconstructed with the changed value. */
  field.set(sysclass, null);

  /* Change the value and load the library. */
  System.setProperty("java.library.path", path+File.pathSeparator+oldPath);
}
catch (Exception ex)
{
  ex.printStackTrace();
}

}
`

That works to load the libraries, but unfortunately, it still doesn’t get around the problem that if JOGL tries to load them and fails (which generates a catchable Error), any further attempts, even with the libraries set properly, result in a ClassDefNotFoundError .

On a related note. How do I catch the expection I get when there’s no jogl.dll found? I’d really like to present the user with a proper dialog (as this also happens on older non-gl capable card’s) but all exception handlers I wrap around new’ing GLCanvas is somehow bypassed?

If you post the stack trace you’re talking about we may be able to figure out a way to do this using only public APIs, but if you look at the source code for com.sun.opengl.impl.NativeLibLoader you can create your own LoaderAction which catches the UnsatisfiedLinkError or similar coming from the System.loadLibrary() call directly and do something different.

Sure thing. The exception is:

Exception in thread “main” java.lang.UnsatisfiedLinkError: no jogl in java.library.path
at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1682)
at java.lang.Runtime.loadLibrary0(Runtime.java:822)
at java.lang.System.loadLibrary(System.java:992)
at com.sun.opengl.impl.NativeLibLoader$1.run(NativeLibLoader.java:66)
at java.security.AccessController.doPrivileged(Native Method)
at com.sun.opengl.impl.NativeLibLoader.loadCore(NativeLibLoader.java:64)
at com.sun.opengl.impl.windows.WindowsGLDrawableFactory.(WindowsGLDrawableFactory.java:59)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:164)
at javax.media.opengl.GLDrawableFactory.getFactory(GLDrawableFactory.java:106)
at javax.media.opengl.GLCanvas.(GLCanvas.java:113)
at javax.media.opengl.GLCanvas.(GLCanvas.java:82)
at firstlayout.render.jogl.JOGLRender.initialize(JOGLRender.java:242)

That’s the same error I got before switching to a cutomized library loader… the problem is that even if you do catch it and reload the libraries, some of the JOGL classes are improperly loaded, and they won’t instantiate (they’ll give NoClassFound errors or something like that when they try to use the native factories).