One and only one of my hundreds of users has trouble starting my Java desktop app. It only starts for him about one-third of the time. The other two-thirds of the time a NullPointerException is thrown at startup:
Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
at java.util.Hashtable.put(Hashtable.java:394)
at javax.swing.JEditorPane.registerEditorKitForContentType(JEditorPane.java:1327)
at javax.swing.JEditorPane.registerEditorKitForContentType(JEditorPane.java:1309)
at javax.swing.JEditorPane.loadDefaultKitsIfNecessary(JEditorPane.java:1387)
at javax.swing.JEditorPane.getKitTypeRegistry(JEditorPane.java:1344)
at javax.swing.JEditorPane.getEditorKitClassNameForContentType(JEditorPane.java:1340)
at javax.swing.JTextPane.<init>(JTextPane.java:76)
at myapp.Launcher$1.run(Launcher.java:13)
at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:209)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:633)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:296)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:211)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:201)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:196)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:188)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:122)
I've followed the stack trace to find that the cause is that
Thread.currentThread().getContextClassLoader()
in JEditorPane is returning null.
Googling reveals that this is a sporadic, very infrequent, and mysterious problem that affects a few people.
My question is, what can I do as a work-around? This might work, if I call it before creating an EditorPane:
Thread.currentThread().setContextClassLoader(MyClass.class.getClassLoader());
But I don't really understand classloaders as well as I would like (and I've tried to understand them better). I feel that changing the contextClassLoader in the EDT could have bad ramifications.
Any ideas what I can do?
EDIT: I had some correspondence with someone who understands Java ClassLoaders well. It seems this is an obscure ClassLoader race condition. That is, a bug in Java.
If the code in
JEditorPane.registerEditorKitForContentType
does not check for a null return value in the above code, this is a bug inJEditorPane
. Note thatMyClass.class.getClassLoader()
may also return null. The only one you can rely on is the system ClassLoader.The pattern for setting the context
ClassLoader
for an invocation usually looks something like this:The value that should be set via
setContextClassLoader
will depend on the intent of the code that is consuming it and the design of theClassLoader
framework you are running in.In a stand-alone application, you can probably get away with just using this
ClassLoader
(passing in a ref to the current class):In a ClassLoader-sensitive plug-in framework (a Java EE server would be a prime example), it would pay to understand the nature and usage of the loading scheme.