The changes made in Jogl 2.1.4 make it impossible to run a Java3D application without crashing in webstart. It works fine in stand-alone applications but crashes when ran in webstart. Before crashing, the following exceptions are thrown: java.lang.IllegalArgumentException: java.lang.reflect.InvocationTargetException at jogamp.nativewindow.NativeWindowFactoryImpl.getAWTNativeWindow(NativeWindowFactoryImpl.java:107) at jogamp.nativewindow.NativeWindowFactoryImpl.getNativeWindowImpl(NativeWindowFactoryImpl.java:66) at javax.media.nativewindow.NativeWindowFactory.getNativeWindow(NativeWindowFactory.java:583) at javax1.media.j3d.JoglPipeline.createNewContext(JoglPipeline.java:6374) at javax1.media.j3d.Canvas3D.createNewContext(Canvas3D.java:4611) at javax1.media.j3d.Canvas3D.createNewContext(Canvas3D.java:2381) at javax1.media.j3d.Renderer.doWork(Renderer.java:881) at javax1.media.j3d.J3dThread.run(J3dThread.java:271) Caused by: java.lang.reflect.InvocationTargetException at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) at sun.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source) at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source) at java.lang.reflect.Constructor.newInstance(Unknown Source) at jogamp.nativewindow.NativeWindowFactoryImpl.getAWTNativeWindow(NativeWindowFactoryImpl.java:105) ... 7 more Caused by: java.lang.NullPointerException at sun.awt.SunToolkit.getSystemEventQueueImplPP(Unknown Source) at sun.awt.SunToolkit.getSystemEventQueueImplPP(Unknown Source) at sun.awt.SunToolkit.getSystemEventQueueImpl(Unknown Source) at java.awt.Toolkit.getEventQueue(Unknown Source) at java.awt.EventQueue.isDispatchThread(Unknown Source) at com.jogamp.common.util.awt.AWTEDTExecutor.invoke(AWTEDTExecutor.java:48) at com.jogamp.nativewindow.awt.JAWTWindow$JAWTComponentListener.<init>(JAWTWindow.java:166) at com.jogamp.nativewindow.awt.JAWTWindow$JAWTComponentListener.<init>(JAWTWindow.java:127) at com.jogamp.nativewindow.awt.JAWTWindow.<init>(JAWTWindow.java:119) at jogamp.nativewindow.jawt.windows.WindowsJAWTWindow.<init>(WindowsJAWTWindow.java:60) ... 12 more DefaultRenderingErrorListener.errorOccurred: CONTEXT_CREATION_ERROR: Renderer: Error creating Canvas3D graphics context graphicsDevice = Win32GraphicsDevice[screen=0] canvas = runiter.grapher.math.Sheet$CapturingCanvas3D[canvas0,0,0,386x429] Exception in thread "J3D-BehaviorScheduler-1" java.lang.IllegalStateException: zip file closed at java.util.zip.ZipFile.ensureOpen(Unknown Source) at java.util.zip.ZipFile.getEntry(Unknown Source) at java.util.jar.JarFile.getEntry(Unknown Source) at com.sun.deploy.cache.CachedJarFile.getEntry(Unknown Source) at java.util.jar.JarFile.getJarEntry(Unknown Source) at com.sun.deploy.security.DeployURLClassPath$JarLoader.getResource(Unknown Source) at com.sun.deploy.security.DeployURLClassPath.getResource(Unknown Source) at java.net.URLClassLoader$1.run(Unknown Source) at java.net.URLClassLoader$1.run(Unknown Source) at java.security.AccessController.doPrivileged(Native Method) at java.net.URLClassLoader.findClass(Unknown Source) at com.sun.jnlp.JNLPClassLoader.findClass(Unknown Source) at java.lang.ClassLoader.loadClass(Unknown Source) at java.lang.ClassLoader.loadClass(Unknown Source) at java.lang.ClassLoader.loadClass(Unknown Source) at javax1.media.j3d.BehaviorScheduler.doWork(BehaviorScheduler.java:167) at javax1.media.j3d.J3dThread.run(J3dThread.java:271) gouessej believes that the change between January 25 and January 31 caused a regression as a result of this change: https://github.com/sgothel/jogl/commit/b7fafd30ffc5eac73880b264043582d74175a394 https://github.com/hharrison/java3d-core/blob/master/src/classes/share/javax/media/j3d/JoglPipeline.java#L6374 The stack trace clearly shows that we pass in the constructor of JAWTComponentListener. Although we couldn't reproduce this problem in a pure Jogl application. As it stands this problem only occurs when Jogl is called from Java3D. gouessej believes that this change just exposes us to this bug in Oracle Java: http://bugs.java.com/view_bug.do?bug_id=8017776 It also looks like the following Java bugs: http://bugs.java.com/view_bug.do?bug_id=8019274 He suggested the following workaround which worked in OpenJDK 1.7 update 45 and Icedtea Webstart but didn't work in Windows with Oracle JVM: if(AppContext.getAppContext() == null){ SunToolkit.createNewAppContext(); } TESTCASE: This problem is easy to reproduce. Even the HelloWorld of Java3D triggers this crash if run from webstart. Testcase jnlp: http://www.runiter.com/webstart/test_gc3/grapher.jnlp Testcase Source Code: public class MainApplication { public static void main(final String[] args) { final SimpleUniverse universe = new SimpleUniverse(); final BranchGroup group = new BranchGroup(); group.addChild(new ColorCube(0.3)); universe.getViewingPlatform().setNominalViewingTransform(); universe.addBranchGraph(group); } }
(In reply to comment #0) > He suggested the following workaround which worked in OpenJDK 1.7 update 45 > and Icedtea Webstart but didn't work in Windows with Oracle JVM: > > if(AppContext.getAppContext() == null){ > SunToolkit.createNewAppContext(); > } > Actually, OpenJDK supports your example as is without my workaround as it is NOT concerned by this bug.
(In reply to comment #1) > Actually, OpenJDK supports your example as is without my workaround as it is > NOT concerned by this bug. This has been confirmed by 'runiter' as well, i.e. bug only affects Oracle's JRE/AWT. Question now is whether we should and can provide a workaround and why this only happens w/ Java3D. I added Harvey to this bug (Java3D ..). I changed the type to 'ANNOTATION', since it documents another bug. Reduced to 'major' .. At runiter, maybe you can go ahead and test certain remedies and try a workaround ?
I couldn't find a workaround so far, but I'm going to try to remotely debug webstart+Java3D to see if I can find a cause or workaround that way. I'll keep you updated.
My debug result shows that in webstart mode, the value of AppContext.getAppContext() is indeed null at this line: javax.media.j3d.JoglPipeline.createNewContext(JoglPipeline.java:6374) Interestingly when JoglPipeline is created AppContext.getAppContext() is not null. But since JoglPipeline.createNewContext is called from javax.media.j3d.Renderer what matters is the context at the time of the creation of Renderer object. My debug result shows that when Renderer is created, the value of AppContext.getAppContext() is indeed null. The cause of this can be traced back to javax.media.j3d.MasterControlThread which is in charge of creating Renderer. MasterControlThread has a non-null context at the time of its creation so I'm not sure why MasterControlThread.run() method ends up with a null context.
Thank you very much for debugging this, I know exactly why this happens, I believe MasterControl puts all the threads it manages in its own ThreadGroup, I won't have time to fix this before Saturday, but I'm pretty sure it's a trivial fix....THANK YOU very much for the analysis.
Glad I could be of help :) I will await your update hopefully in the weekend.
Hi Harvey, any updates on this? I noticed Java3D hasn't change in github yet.
diff --git a/src/classes/share/javax/media/j3d/JoglPipeline.java b/src/classes/share/javax/media/j3d/JoglPipeline.java index 2d3c073..3f40b2c 100644 --- a/src/classes/share/javax/media/j3d/JoglPipeline.java +++ b/src/classes/share/javax/media/j3d/JoglPipeline.java @@ -36,6 +36,7 @@ import java.awt.GraphicsDevice; import java.awt.GraphicsEnvironment; import java.io.UnsupportedEncodingException; +import java.lang.reflect.Field; import java.lang.reflect.Method; import java.nio.Buffer; import java.nio.ByteBuffer; @@ -46,6 +47,7 @@ import java.security.PrivilegedAction; import java.util.ArrayList; import java.util.List; +import java.util.Map; import java.util.StringTokenizer; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -99,10 +101,20 @@ private static final int MIN_FRAME_SIZE = 1; private GLProfile profile; + + private Object mainThreadContext; // Fix for Bug 983 + /** * Constructor for singleton JoglPipeline instance */ protected JoglPipeline() { + // Fix for Bug 983 + try { + // Retrieve main thread AppContext instance by reflection + mainThreadContext = Class.forName("sun.awt.AppContext").getMethod("getAppContext").invoke(null); + } catch (final Throwable ex) { + // Let's consider app context is not necessary for the program + } } /** @@ -6350,6 +6362,29 @@ surface.unlockSurface(); } } + + // Fix for Bug 983 + private void checkAppContext() { + if (mainThreadContext != null) { + try { + // Check by reflection that sun.awt.AppContext.getAppContext() doesn't return null + // (required by ImageIO.write() and other JMF internal calls) to apply workaround proposed at + // http://stackoverflow.com/questions/17223304/appcontext-is-null-from-rmi-thread-with-java-7-update-25 + final Class<?> appContextClass = Class.forName("sun.awt.AppContext"); + if (appContextClass.getMethod("getAppContext").invoke(null) == null) { + final Field field = appContextClass.getDeclaredField("threadGroup2appContext"); + field.setAccessible(true); + final Map threadGroup2appContext = (Map)field.get(null); + final ThreadGroup currentThreadGroup = Thread.currentThread().getThreadGroup(); + threadGroup2appContext.put(currentThreadGroup, mainThreadContext); + } + } catch (final Throwable ex) { + // Let's consider app context is not necessary for the program + } + // Don't need mainThreadContext anymore + mainThreadContext = null; + } + } // This is the native method for creating the underlying graphics context. @Override @@ -6357,6 +6392,8 @@ Context shareCtx, boolean isSharedCtx, boolean offScreen) { if (VERBOSE) System.err.println("JoglPipeline.createNewContext()"); + + checkAppContext(); GLDrawable glDrawable = null; GLContext glContext = null;
Please apply the above patch which fixes this issue. Also, it is possible that we no longer need the following commit: https://github.com/hharrison/java3d-utils/commit/14206478b7a5bf628b59094c92d5727291c7c2bf The above commit fixed the issue for JCanvas only. I think my patch which replicates the code in the above commit may cover both JCanvas and Canvas3D but I didn't test for that so can't be sure. Either way the problem report in this bug is resolved with my patch. I tested in my Windows machine. Other tests are welcomed.
Applied to j3dcore commit: bdda2ac20bfef85271da764d1989ec3434d5c67a Applied removal of the old JCanvas3D workaround in j3dutils commit: 1f025a8787edec6e2ae1eab3a3fd0eb59319e3c4
(In reply to comment #10) > Applied to j3dcore > commit: bdda2ac20bfef85271da764d1989ec3434d5c67a > > Applied removal of the old JCanvas3D workaround in j3dutils > commit: 1f025a8787edec6e2ae1eab3a3fd0eb59319e3c4 Pls consider using workaround of Bug 1004 Comment 4, i.e.: jogl aa1c04ebee23d0803880d6d68ae73109c1a5c178, uses gluegen f39100b35d0833764f2220e487ea7ea05ed87352 This will be crucial especial in cases of multiple AppContext per ClassLoader .. see comment.
(In reply to comment #11) > (In reply to comment #10) > > Applied to j3dcore > > commit: bdda2ac20bfef85271da764d1989ec3434d5c67a > > > > Applied removal of the old JCanvas3D workaround in j3dutils > > commit: 1f025a8787edec6e2ae1eab3a3fd0eb59319e3c4 > > Pls consider using workaround of Bug 1004 Comment 4, i.e.: > jogl aa1c04ebee23d0803880d6d68ae73109c1a5c178, > uses gluegen f39100b35d0833764f2220e487ea7ea05ed87352 > > This will be crucial especial in cases of multiple AppContext > per ClassLoader .. see comment. That would be _excellent_, i.e. the image format auto-detection! IMHO it would be nice to have a static method returning the type, as well as an overloaded 'load' texture method. Nice!
(In reply to comment #12) > (In reply to comment #11) > > (In reply to comment #10) > > > Applied to j3dcore > > > commit: bdda2ac20bfef85271da764d1989ec3434d5c67a > > > > > > Applied removal of the old JCanvas3D workaround in j3dutils > > > commit: 1f025a8787edec6e2ae1eab3a3fd0eb59319e3c4 > > > > Pls consider using workaround of Bug 1004 Comment 4, i.e.: > > jogl aa1c04ebee23d0803880d6d68ae73109c1a5c178, > > uses gluegen f39100b35d0833764f2220e487ea7ea05ed87352 > > > > This will be crucial especial in cases of multiple AppContext > > per ClassLoader .. see comment. > > That would be _excellent_, i.e. the image format auto-detection! > > IMHO it would be nice to have a static method returning the type, > as well as an overloaded 'load' texture method. > > Nice! Are you sure that you comment the good bug report?
(In reply to comment #13) > > > > That would be _excellent_, i.e. the image format auto-detection! > > > > IMHO it would be nice to have a static method returning the type, > > as well as an overloaded 'load' texture method. > > > > Nice! > > Are you sure that you comment the good bug report? sorry for bug 982 .. pls dismiss