Bug 460

Summary: NPE using the GLCanvas.getFactory() method with minimal setup.
Product: [JogAmp] Jogl Reporter: François Coupal <fcoupal>
Component: openglAssignee: Sven Gothel <sgothel>
Status: VERIFIED FIXED    
Severity: major    
Priority: ---    
Version: 2   
Hardware: pc_x86_32   
OS: linux   
Type: --- SCM Refs:
2cbab63bd6c230d31b8ae6f1d794ad49bf23bb53 e8b25a1d6c9fe06b68bb16c0ea19276f97e28414 694eb0c9309b3705a8bdb582f0c287aa77169996
Workaround: ---
Attachments: JUnit test case for recreating the NPE.
File needed to make the OneTriangleAWT example work.
Working example using a Frame.

Description François Coupal 2011-01-18 21:49:25 CET
NullPointerException pops up when following code is executed.

I executed this test on Ubuntu (Linux i386) with every native library and every module library (nativewindows, jogl, newt, jogl.test, ant, junit, ant-junit and gluegen) using the "*.all.*" variation. Therefore I think every single class was present, save for the JDK packages.

The goal of this test is to extract every OpenGL extension supported by the graphic card.

*******

import java.util.Collections;
import java.util.SortedSet;
import java.util.TreeSet;

import javax.media.nativewindow.AbstractGraphicsDevice;
import javax.media.opengl.DefaultGLCapabilitiesChooser;
import javax.media.opengl.GL;
import javax.media.opengl.GL2;
import javax.media.opengl.GLCapabilities;
import javax.media.opengl.GLCapabilitiesChooser;
import javax.media.opengl.GLCapabilitiesImmutable;
import javax.media.opengl.GLContext;
import javax.media.opengl.GLDrawableFactory;
import javax.media.opengl.GLPbuffer;
import javax.media.opengl.GLProfile;
import javax.media.opengl.awt.GLCanvas;

public class testJOGL2 {
        public static void main(String[] args) {
                GLProfile.initSingleton(true);
                GLCapabilities caps = new GLCapabilities(GLProfile.get(GLProfile.GL2));
                GLCanvas glc = new GLCanvas(caps);
                GLDrawableFactory usine = glc.getFactory();
                GLCapabilitiesImmutable glci = glc.getChosenGLCapabilities();
                GLCapabilitiesChooser glcc = new DefaultGLCapabilitiesChooser();
                AbstractGraphicsDevice agd = usine.getDefaultDevice();
               
                GLPbuffer pbuffer = usine.createGLPbuffer(agd, glci, glcc, 256, 256, null);
                GLContext context = pbuffer.getContext();
                context.makeCurrent();
                GL2 gl = pbuffer.getContext().getGL().getGL2();
               
                String extensions = gl.glGetString(GL.GL_EXTENSIONS);
                String[] tabExtensions = extensions.split(" ");
                SortedSet<String> setExtensions = new TreeSet<String>();
                Collections.addAll(setExtensions, tabExtensions);
                System.out.println(setExtensions);
        }
}

*********

Here is the console output:

Info: XInitThreads() called for concurrent Thread support
Exception in thread "main" java.lang.NullPointerException
        at javax.media.opengl.awt.GLCanvas.getFactory(GLCanvas.java:694)
        at testJOGL2.main(testJOGL2.java:24)
Comment 1 François Coupal 2011-01-20 21:07:24 CET
Additional Information when run with debug information:

I use JDK 1.6.0_23.

**** Manifest file ******

Manifest-Version: 1.0

Implementation-Title: Java Bindings for OpenGL Runtime Environment

Implementation-Version: 2.0-b11-20101213

Specification-Vendor: JogAmp Community

Created-By: 1.6.0_22-b04 (Sun Microsystems Inc.)

Implementation-URL: http://jogamp.org/

Ant-Version: Apache Ant 1.8.0

Implementation-Commit: e735c312c874ae6abc401b4765b24a83f5238a99

Implementation-Vendor: JogAmp Community

Trusted-Library: true

Implementation-Vendor-Id: com.jogamp

Specification-Title: Java Bindings for OpenGL API Specification

Implementation-Branch: rc

Specification-Version: 2.0

Extension-Name: javax.media.opengl

*************************

java.lang.Throwable: Info: NativeWindowFactory.initSingleton(true)
	at javax.media.nativewindow.NativeWindowFactory.initSingleton(NativeWindowFactory.java:155)
	at javax.media.opengl.GLProfile.initProfilesForDefaultDevices(GLProfile.java:1090)
	at javax.media.opengl.GLProfile.access$000(GLProfile.java:66)
	at javax.media.opengl.GLProfile$1.run(GLProfile.java:111)
	at java.security.AccessController.doPrivileged(Native Method)
	at javax.media.opengl.GLProfile.initSingleton(GLProfile.java:109)
	at testJOGL2.main(testJOGL2.java:20)
Info: XInitThreads() called for concurrent Thread support
X11Util.isFirstX11ActionOnProcess: true
NativeWindowFactory.registerFactory() interface javax.media.nativewindow.NativeWindow -> com.jogamp.nativewindow.impl.NativeWindowFactoryImpl@148aa23
NativeWindowFactory firstUIActionOnProcess true
NativeWindowFactory isAWTAvailable false, defaultFactory com.jogamp.nativewindow.impl.NativeWindowFactoryImpl@148aa23
GraphicsConfigurationFactory.registerFactory() class javax.media.nativewindow.x11.X11GraphicsDevice -> com.jogamp.nativewindow.impl.x11.X11GraphicsConfigurationFactory@763f5d
GraphicsConfigurationFactory.registerFactory() interface javax.media.nativewindow.AbstractGraphicsDevice -> com.jogamp.nativewindow.impl.DefaultGraphicsConfigurationFactoryImpl@186768e
GraphicsConfigurationFactory.registerFactory() class javax.media.nativewindow.x11.X11GraphicsDevice -> com.jogamp.opengl.impl.x11.glx.X11GLXGraphicsConfigurationFactory@14a8cd1
X11 Display(NULL) <:0.0>
GraphicsConfigurationFactory.registerFactory() class javax.media.nativewindow.egl.EGLGraphicsDevice -> com.jogamp.opengl.impl.egl.EGLGraphicsConfigurationFactory@1319c
java.lang.Exception: X11Util.Display: Created new NamedX11Display[:0.0, 0x96d3e90, refCount 1, unCloseable false]. Thread main-SharedResourceRunner
	at com.jogamp.nativewindow.impl.x11.X11Util.createDisplay(X11Util.java:315)
	at com.jogamp.opengl.impl.x11.glx.X11GLXDrawableFactory$SharedResourceImplementation.createSharedResource(X11GLXDrawableFactory.java:162)
	at com.jogamp.opengl.impl.SharedResourceRunner.run(SharedResourceRunner.java:201)
	at java.lang.Thread.run(Thread.java:619)
chooseCapabilities: Using recommendedIndex: idx 0
Exception in thread "main" java.lang.NullPointerException
	at javax.media.opengl.awt.GLCanvas.getFactory(GLCanvas.java:694)
	at testJOGL2.main(testJOGL2.java:23)
java.lang.Exception: X11Util.Display: Closing new NamedX11Display[:0.0, 0x96d3e90, refCount 1, unCloseable false]. Thread main-SharedResourceRunner
	at com.jogamp.nativewindow.impl.x11.X11Util.closeDisplay(X11Util.java:340)
	at javax.media.nativewindow.x11.X11GraphicsDevice.close(X11GraphicsDevice.java:85)
	at com.jogamp.opengl.impl.x11.glx.X11GLXDrawableFactory$SharedResourceImplementation.releaseSharedResource(X11GLXDrawableFactory.java:235)
	at com.jogamp.opengl.impl.SharedResourceRunner.releaseSharedResources(SharedResourceRunner.java:240)
	at com.jogamp.opengl.impl.SharedResourceRunner.run(SharedResourceRunner.java:224)
	at java.lang.Thread.run(Thread.java:619)
java.lang.Exception: X11Util.Display: Shutdown (close open / pending Displays: false, open (no close attempt): 0/0, open (no close attempt and uncloseable): 0)
	at com.jogamp.nativewindow.impl.x11.X11Util.shutdown(X11Util.java:196)
	at com.jogamp.opengl.impl.x11.glx.X11GLXDrawableFactory.shutdownInstance(X11GLXDrawableFactory.java:313)
	at javax.media.opengl.GLDrawableFactory.shutdownImpl(GLDrawableFactory.java:200)
	at javax.media.opengl.GLDrawableFactory.access$100(GLDrawableFactory.java:90)
	at javax.media.opengl.GLDrawableFactory$2.run(GLDrawableFactory.java:171)
	at java.lang.Thread.run(Thread.java:619)
Comment 2 Sven Gothel 2011-02-25 05:43:37 CET
Was fixed dec 2011:
- 2cbab63bd6c230d31b8ae6f1d794ad49bf23bb53
- e8b25a1d6c9fe06b68bb16c0ea19276f97e28414
Comment 3 François Coupal 2011-03-07 16:33:51 CET
Created attachment 238 [details]
JUnit test case for recreating the NPE.
Comment 4 François Coupal 2011-03-07 16:34:33 CET
Created attachment 239 [details]
File needed to make the OneTriangleAWT example work.
Comment 5 François Coupal 2011-03-07 16:36:12 CET
Created attachment 240 [details]
Working example using a Frame.

You can use this file to change behavior depending on what you want to acheive. To make it work (show the exetnsions), just leave as is. If you want to make it crash, prevent the Frame from being set visible in any way.
Comment 6 François Coupal 2011-03-08 15:44:04 CET
Re-opening the bug.

I've noticed the NPE error is created in "toString()" methods when throwing exceptions.

Simply put, in an insufficent context (missing JARs, unavailiable ressources, no profile possible for whatever reason), the exception mechanism tries to make a long string of static info, but these info point to "null" members because of the botched initialisation of the context, and thus turn a normal exception into a NullPointerException.

This behavior is very easy to reproduce in the class GLProfile. Just by looking at the source code I was able to identify about 3-4 cases where nullity is not checked when accessing static objects. (example, line 1283 is VERY likely to throw an NPE when an incorrect initialisation occurs. GLCanvas:748 is another culprit).

By getting rid of these NPEs, it would be much easier to identify the real problems behind the initialization sequence.
Comment 7 François Coupal 2011-03-08 15:45:42 CET
This is the correct state for an open bug. Sorry for the double setting. I'm not very familiar with BugZilla.
Comment 8 Sven Gothel 2011-03-21 07:41:40 CET
thx a lot ..

if you have more 'ideas' / hints for GLPRofile NPEs .. please let us know