Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8115597

NPE in JFX 2.2 when loading a controls class before an Application has been instantiated

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Fixed
    • Icon: P4 P4
    • 7u6
    • 7u6
    • javafx
    • JFX 2.2, downloaded on June 15th, so probably build 13. Tested under Windows 7 Pro, 64 Bit, 8 GB RAM, Java 7 Update 5 (not installed JFX 2.1 which ships with J7U5, but installed JFX 2.2 manually instead).

      I develop a JFX app in Clojure. With JFX 2.1 the program compiles/runs fine. But under JFX 2.2 it doesn't, and runs instead into an NPE.
      It can be reproduced easily by importing Classes from the javafx.scene.control package.
      Here the NPE which I see during building an überjar:

      Exception:
      Compiling foo.bar
      Exception in thread "main" java.lang.ExceptionInInitializerError, compiling:(bar.clj:5)
       at clojure.lang.Compiler$InvokeExpr.eval(Compiler.java:3387)
       at clojure.lang.Compiler.compile1(Compiler.java:7035)
       at clojure.lang.Compiler.compile1(Compiler.java:7025)
       at clojure.lang.Compiler.compile(Compiler.java:7097)
       at clojure.lang.RT.compile(RT.java:387)
       at clojure.lang.RT.load(RT.java:427)
       at clojure.lang.RT.load(RT.java:400)
       at clojure.core$load$fn__4890.invoke(core.clj:5415)
       at clojure.core$load.doInvoke(core.clj:5414)
       at clojure.lang.RestFn.invoke(RestFn.java:408)
       at clojure.core$load_one.invoke(core.clj:5227)
       at clojure.core$compile$fn__4895.invoke(core.clj:5426)
       at clojure.core$compile.invoke(core.clj:5425)
       at user$eval31.invoke(NO_SOURCE_FILE:1)
       at clojure.lang.Compiler.eval(Compiler.java:6511)
       at clojure.lang.Compiler.eval(Compiler.java:6501)
       at clojure.lang.Compiler.eval(Compiler.java:6477)
       at clojure.core$eval.invoke(core.clj:2797)
       at clojure.main$eval_opt.invoke(main.clj:297)
       at clojure.main$initialize.invoke(main.clj:316)
       at clojure.main$null_opt.invoke(main.clj:349)
       at clojure.main$main.doInvoke(main.clj:427)
       at clojure.lang.RestFn.invoke(RestFn.java:421)
       at clojure.lang.Var.invoke(Var.java:419)
       at clojure.lang.AFn.applyToHelper(AFn.java:163)
       at clojure.lang.Var.applyTo(Var.java:532)
       at clojure.main.main(main.java:37)
      Caused by: java.lang.ExceptionInInitializerError
       at java.lang.Class.forName0(Native Method)
       at java.lang.Class.forName(Class.java:186)
       at foo.bar$loading__4784__auto__.invoke(bar.clj:5)
       at clojure.lang.AFn.applyToHelper(AFn.java:159)
       at clojure.lang.AFn.applyTo(AFn.java:151)
       at clojure.lang.Compiler$InvokeExpr.eval(Compiler.java:3382)
       ... 26 more
      Caused by: java.lang.NullPointerException
       at com.sun.glass.ui.Screen.getMainScreen(Screen.java:15)
       at com.sun.javafx.tk.quantum.QuantumToolkit.getPrimaryScreen(QuantumToolkit.java:594)
       at javafx.stage.Screen.updateConfiguration(Screen.java:102)
       at javafx.stage.Screen.checkDirty(Screen.java:97)
       at javafx.stage.Screen.getPrimary(Screen.java:176)
       at com.sun.javafx.Utils.isQVGAScreen(Utils.java:813)
       at javafx.scene.control.UAStylesheetLoader$1.run(UAStylesheetLoader.java:69)
       at java.security.AccessController.doPrivileged(Native Method)
       at javafx.scene.control.UAStylesheetLoader.loadUAStylesheet(UAStylesheetLoader.java:58)
       at javafx.scene.control.UAStylesheetLoader.doLoad(UAStylesheetLoader.java:51)
       at javafx.scene.control.Control.(Control.java:92)
       ... 32 more


      Since JFX 2.2 something has changed in some controls (Button, Label, etc). They maybe expect that an Application instance already exists when they get loaded?
      In Clojure, development occurs in an organic manner. I start the JVM, without any code. Now in the running JVM I compile Clojure code to bytecode. I discovered this issue after developing a little tool, which I started developing without importing anything from javafx.scene.control.*. Only after the JVM was running I instantiated an Application and updated it frequently. Now I imported Buttons and Labels, etc. and created instances of them and added them to a Scene which became the Scene of my primary Stage. This worked fine. However, after I wrote my little tool I wanted to compile it into an überjar, which caused this NPE.
      Please take a look at this Java code which is part of the Clojure compiler — this code imports classes:
      https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/Compiler.java#L581

      I am not certain what is going on, but this is my suspicion:
      When I do (import javafx.scene.control.Label) for example that RT.classForName(c) call from the code snippet above runs, which I think triggers the instantiation of static variables inside the Label class, and this instantiation expects that an Application already exists.
      This was not the case in all JFX versions before, and it unfortunately breaks non-Java JFX apps.

            jgiles Jonathan Giles
            athiemejfx Andre Thieme (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

              Created:
              Updated:
              Resolved:
              Imported: