2016-08-29 10 views
1

私のアプリケーションで突然奇妙な問題が発生しましたが、問題を特定できるかどうかはわかりません。私はSCCEEでバグを再現できませんでしたが、誰かが以下の2つの質問に答えることによって何が起こるのか理解する助けになるかもしれません。EDTが "system"グループに変更され、Thread.currentThread()。getContextClassLoader()がnullです

コンテキスト:

私が持っているが、基本的にこの:

 ... 
     Some treatment 
     ->call to json-io to parse a Json String to Java Objects. see below 
     ... 

     SwingUtilities.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       myUI.start();//starts my user interface 
      } 
     }); 

通常、すべてが正常になります。しかし、私はJson IO(JsonをJavaに解析し、私が一般的に問題なく使用するライブラリ)への呼び出しを処理に追加しました。

さて、私の他のライブラリの一つは叫んさ:

Caused by: java.lang.NullPointerException 
    at net.sourceforge.jeuclid.elements.support.ClassLoaderSupport.loadClass(ClassLoaderSupport.java:65) 

は、いくつかの研究の後、私はそれがThread.currentThread().getContextClassLoader()ために戻っnullであることを発見しました。 、最後に

SwingUtilities.invokeLater(new Runnable() { 
     @Override 
     public void run() { 
      System.out.println(Thread.currentThread()); 
      //returns Thread[AWT-EventQueue-0,6,system] instead of Thread[AWT-EventQueue-0,6,main] 
      myUI.start();//starts my user interface 
     } 
    }); 

は、私は上記のrun()に行って、2人の処刑の唯一の違いは、現在のグループmainに所属していたイベントの送出スレッドがsystemに属することであることを発見しました

:私は

 SwingUtilities.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       Thread.currentThread().setContextClassLoader(ClassLoader.getSystemClassLoader()); 
       myUI.start();//starts my user interface 
      } 
     } 
    }); 

質問で問題を解決できます

1)EDT変更グループにはどのようなことがありますか?

2)Thread.currentThread().setContextClassLoader(ClassLoader.getSystemClassLoader());を書くとどうなりますか?良いアイデアか悪いアイデアですか?

+0

ここで悪い考えは、EDTで長い操作(JSON解析)を実行することです。これは、UIへの迅速な操作と変更のためにのみ使用されることになっています。 – RealSkeptic

+0

しかし、Jsonの解析は 'SwingUtilities.invokeLater'の呼び出しの前に行われます。それが不明な場合は申し訳ありません。私を編集させてください。 – Sharcoux

+0

クラスローダーを手動で設定する必要があるのは非常に奇妙です。コンテキストクラスローダーをnullに設定するコードが他にもありますか? – user2864740

答えて

1

SwingUtilities.invokeLaterの呼び出しがEDTの存在に依存する最初のアクションである場合、そのスレッドは副産物として作成されます。したがって、作成されたスレッドは、それを作成したスレッドのスレッドグループを継承します。アプリケーションの最初のアクションとして実行したときにIdeone上で確認することができるよう

ThreadGroup tg=new ThreadGroup("foo"); 
new Thread(tg,()-> 
    SwingUtilities.invokeLater(() -> System.out.println(Thread.currentThread())) 
).start(); 

Thread[AWT-EventQueue-0,6,foo] 

を印刷します。

スレッドグループはコンテキストクラスローダーに影響を与えませんが、それはむしろ同じ原因の症状です。コンテキストクラスローダーは、スレッドが作成されたときにスレッドグループとまったく同じように継承されます。

ClassLoader dummyLoader=new URLClassLoader(new URL[0]); 
Thread.currentThread().setContextClassLoader(dummyLoader); 
SwingUtilities.invokeLater(() -> 
    System.out.println(Thread.currentThread().getContextClassLoader()==dummyLoader)); 

は、trueを印刷します。 (verify on Ideone)

だから明らかに、EDTの作成を開始し、SwingUtilities.invokeLaterを呼び出すスレッドのコンテキスト・ローダーは、すでにnullである(とそのスレッドはsystemグループです)。コンテキストローダーをClassLoader.getSystemClassLoader()に設定すると、デフォルトに設定されるため、コンテキストローダーがデフォルト以外のローダーに意図的に設定されている環境に遭遇しない限り、悪影響はありません。nullはこのようなケースではありません。つまり、場所を特定すると、nullに設定され、それを修正する場所がより適切です。

+0

私が探していた答えとまったく同じです。ありがとう!私はそれを徹底的に調べます。 – Sharcoux

関連する問題