2009-12-06 25 views
7

私のJavaデスクトップアプリケーションの起動に何百人ものユーザーが苦労しています。それは彼の約3分の1を開始するだけです。時間の他の三分の二は、NullPointerExceptionが発生は、起動時にスローされます。このJavaコンテキストクラスローダーの問題を安全に解決するにはどうすればよいですか?

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) 

私は原因がJEditorPaneので

Thread.currentThread().getContextClassLoader() 

がnullを返すされていることをことを見つけるために、スタックトレースを追ってきました。

これは、散発的で、非常にまれで、神秘的な問題で、少数の人々に影響を与えることが明らかになっています。

私の問題は、回避策として何ができますか?これはEditorPaneを作成する前に、私はそれを呼び出す場合は、うまくいくかもしれない:

Thread.currentThread().setContextClassLoader(MyClass.class.getClassLoader()); 

しかし、私は本当にだけでなく、私は希望としてのクラスローダを理解していない(と私はそれらをよりよく理解しようとしました)。私は、EDTのcontextClassLoaderを変更すると悪影響が及ぶと感じています。

私は何ができますか?

EDIT:Java ClassLoadersをよく理解している人との対応がありました。これは、ClassLoader競合状態が不明瞭なようです。つまり、Javaのバグです。

+0

ユーザーのJavaランタイムをアップグレードする機会はありますか? –

+0

@Tamás、これはMacアプリです。私は彼に最新のMac Javaアップデートを試すように頼んだ。 –

答えて

4
Thread.currentThread().getContextClassLoader() 

JEditorPane.registerEditorKitForContentTypeのコードは上記のコードではnullの戻り値をチェックしない場合、これはJEditorPaneでバグです。 MyClass.class.getClassLoader()may also return nullに注意してください。信頼できる唯一のものはsystem ClassLoaderです。

呼び出しのコンテキストClassLoaderを設定するためのパターンは、通常、このようなものになります。setContextClassLoaderを経由して設定されるべき値は、それを消費しているコードとデザインの意図に依存します

Thread thread = Thread.currentThread(); 
ClassLoader old = thread.getContextClassLoader(); 
thread.setContextClassLoader(fooClassLoader); 
try { 
    // do call that depends on context ClassLoader 
} finally { 
    thread.setContextClassLoader(old); 
} 

を。あなたは、スタンドアロンのアプリケーションでは

で実行されているClassLoaderフレームワークを、あなたはおそらく(現在のクラスへの参照を渡して)このClassLoaderを使用して逃げることができます:

private ClassLoader findClassLoaderForContext(Class<?> c) { 
    ClassLoader context = Thread.currentThread().getContextClassLoader(); 
    ClassLoader me = c.getClassLoader(); 
    ClassLoader system = ClassLoader.getSystemClassLoader(); 
    return (context == null) ? (me == null) ? system : me : context; 
} 

ClassLoaderに敏感なプラグインフレームワーク(Java EEサーバーが最も重要な例です)では、読み込みスキームの性質と使用方法を理解するために費用がかかります。

+0

私はあなたが呼び出しのためのコンテキストクラスローダーを設定するために与えたそのパターンを試しました。 contextclassloaderの他の用途のために潜在的に物事をねじ込むことはないので、私はそれが好きです。 –

関連する問題