Google Guice 4.1.0依存性注入を使用したデスクトップのSwingアプリケーションがあります。開発中はすべて正常に機能しましたが、同僚がアプリケーションを実行しようとしたときに何か不思議なことが起きました。GuiceはJPanelを拡張するクラスをスーパーコンストラクタへの呼び出しでインスタンス化できません
JPanel
を拡張するMainWindow
クラスがあります。コンストラクタでは、このクラスはそれ自身が注入可能ないくつかのコントローラを取ります。主な方法ではGuiceインジェクタが作成されます。次に、インジェクタはMainWindow
(injector.getInstance(MainWindow.class)
)をインスタンス化しようとします。そして、それはNullPointerException
で失敗しました!
これは私のコンピュータでは起こりません。同じJDKを使用しています。ここで
問題のあるコード(注:これは、残念ながら、問題を再現しません):まで剥奪MainWindow
クラスがある
class Main {
private static final Injector injector = Guice.createInjector();
public static void main(String[] args) {
MainWindow mainWindow = injector.getInstance(MainWindow.class);
SwingUtilities.invokeLater(new Runnable() {
public void run() {
mainWindow.createAndShowGUI();
}
});
}
}
ここでトレーススタックです:
class MainWindow extends JPanel {
private final Foo foo;
private final JFrame frame;
@Inject
public MainWindow(Foo foo) {
super(new GridBagLayout()); // <-- NullPointerException
this.foo = foo;
this.frame = new JFrame("title");
}
public void createAndShowGUI() {
// ...
frame.add(this);
frame.pack();
frame.setVisible(true);
}
}
そして、ここではmain()
方法があります例外:
com.google.inject.ProvisionException: Unable to provision, see the following errors:
1) Error injecting constructor, java.lang.NullPointerException
at app.gui.MainWindow.<init>(MainWindow.java:133)
while locating app.gui.MainWindow
1 error
at com.google.inject.internal.InjectorImpl$2.get(InjectorImpl.java:1028) ~[app-1.0-SNAPSHOT.jar:?]
at com.google.inject.internal.InjectorImpl.getInstance(InjectorImpl.java:1054) ~[app-1.0-SNAPSHOT.jar:?]
at app.Main.createAndShowGUI(Main.java:40) ~[app-1.0-SNAPSHOT.jar:?]
at app.Main.access$000(Main.java:26) ~[app-1.0-SNAPSHOT.jar:?]
at app.Main$2.run(Main.java:67) ~[app-1.0-SNAPSHOT.jar:?]
NPE最も驚くべき場所、すなわちMainWindow
(これは133行目)のスーパークラスのコンストラクタの呼び出しでスローされました。私は掘り始め、マニュアルMainWindow
の作成とその依存関係を注入することが正常に動作することが判明:
MainWindow mainWindow = new MainWindow(injector.getInstance(Foo.class));
私は多分、クラスローダが正常に動作しなかったことを疑われたので、私はMainWindow
とJPanel
の両方のログクラスローダで再び試してみました:
System.out.println("MainWindow: " + MainWindow.class.getClassLoader());
System.out.println("JPanel: " + JPanel.class.getClassLoader());
MainWindow mainWindow = injector.getInstance(MainWindow.class);
クラスローダーは(JPanel
は、ブートストラップによってロードされている)異なっているが、今の注入は正常に働いていました。これは、JPanel
クラスがメインメソッドコンテキストに明示的にロードされたためです。
だから私の質問は以下のとおりです。
- 誰でも同様の問題がありましたか?
- 私の間違いですか、それともバグですか?
- これはバグの場合、Guiceで発生しますか?あるいはJRE?
よりJavaとOSの詳細:
- 私はもともとJDK 1.8.0u111でそれを開発したが、その後、JDKの1.8.0u121に切り替えます。
- アプリケーションはJava 6にコンパイルされます。
- JRE 6およびJRE 8(JDK)のWindows 10、バージョン1607(OSビルド14393.693)で、自分のコンピュータで完璧に動作します。
NullPointerException
は、Windows 10、バージョン1511(OSビルド10586.753)、JDK 1.8.0u112、および1.8.0u121の同僚のコンピュータで生成されます。
残念ながら、私は問題を再現する最小限のバージョンを提供できませんでした。ヘック、私は問題を再現することさえできません、それは同僚の環境でのみ起こります。
Guiceの設定ファイルを調べましたか?あなたと同僚の間に違いはありますか? –
@ M.Prokhorov違いはありません。プロジェクトはMavenから構築され、追加の設定は追加されません。さらに、実行時の失敗であり、コンパイルではありません。まったく同じJARが自分のコンピュータ上で動作しますが、彼のコンピュータでは動作しません。それが私か彼によって集められたかどうかは関係ありません。 – Archie
さて、クラスローダーが異なる場合は、実行時の問題です。両方のマシンで、そのログステートメントによって異なるクラスローダーが報告されていますか?インジェクタが呼び出されている間に何か印刷されていますか? –