2013-06-20 17 views
6

我們最近更新到更新21從Java 7更新25,並且現在遇到空指針異常時,從rmi線程調用SwingUtilities.isEventDispatchThread()becuase AppContext.getAppContext( )返回null。AppContext從rmi線程與Java 7更新25

顯示java.lang.NullPointerException在 sun.awt.SunToolkit.getSystemEventQueueImplPP(未知來源)在 sun.awt.SunToolkit.getSystemEventQueueImplPP(未知來源)在 sun.awt.SunToolkit.getSystemEventQueueImpl(未知來源)在 java.awt.Toolkit.getEventQueue(來源不明)處 javax.swing.SwingUtilities.isEventDispatchThread(來源不明) 了java.awt.EventQueue.isDispatchThread(來源不明)在 ... ... 在sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)at sun.reflect.NativeMethodAcce ssorImpl.invoke(未知來源)處 java.lang.reflect.Method.invoke(未知來源) sun.reflect.DelegatingMethodAccessorImpl.invoke(未知來源)在 sun.rmi.server.UnicastServerRef.dispatch(未知來源)在 sun.rmi.transport.Transport $ 1.run(Unknown Source)at sun.rmi.transport.Transport $ 1.run(Unknown Source)at java.security.AccessController.doPrivileged(Native Method)at sun.rmi .transport.Transport.serviceCall(來源不明)處 sun.rmi.transport.tcp.TCPTransport $ ConnectionHandler.run0(未知 來源) sun.rmi.transport.tcp.TCPTransport.handleMessages(來源不明)在 太陽.rmi.transport.tcp.TCPTransport $ ConnectionHandler.run(未經在java.util.concurrent.ThreadPoolExecutor.runWorker(未知 來源)在java.util.concurrent.ThreadPoolExecutor中的$ Worker.run(未知 來源)在java.lang.Thread.run(來源不明)

稱爲 源)

此錯誤僅在web啓動時出現,當我們通過IDE運行我們的應用程序時,它很好。

有沒有人遇到過這個?想知道關於AppContext的最新更新有哪些變化?

在別人看來有與AppContext有點相關的問題在更新後: https://forums.oracle.com/message/11077767#11077767

+0

我不能提供了一個解決方案,但是我們也遇到了與Java 7 Update 25相同的問題。我們有一個基於Swing的應用程序,它是通過Java Webstart進行分發和啓動的。它還充當RMI服務器。當傳入的RMI調用調用EventQueue.isDispatchThread時,我們會得到相同的異常:sun.awt.AppContext#getAppContext()在這種情況下似乎返回null。 Java 7 Update 25對我們的應用程序無用,這是一個嚴重的倒退。試圖應用Bug 4711515的解決方法時,我們會更進一步。但是,然後在JNLPClassLoader.getPermissions發生Nullpointer問題... – Holger

+0

JNLPClassLoader.getPermissons()中的Nullpointer問題在這裏提到:http://stackoverflow.com/questions/17230773/java-7-update-25-makes-our -java-web-start-application-fail-with-no-logging 更新版本存在嚴重錯誤... – Holger

+0

我們在這裏可能有類似的問題:。在我們的應用程序中,客戶端也充當RMI服務器。 –

回答

0

它不是一個最終的答案,但它是一種解決方法,爲我的作品。

應用程序需要保存當前AppContext在EVT:

void invokeLater2(Runnable rn) { 
    if (AppContext.getAppContext() == null) { 
     logger.warning("AppContext is null, using EVT AppContext" 
      + " through SunToolKit"); 
     sun.awt.SunToolkit.invokeLaterOnAppContext(evtContext, rn); 
    } else { 
     SwingUtilities.invokeLater(rn); 
    } 
} 

AppContext evtContext; //field 

    SwingUtilities.invokeLater(new Runnable() { 
     public void run() { 
      evtContext = AppContext.getAppContext(); 
     } 
    }); 

然後所有SwingUtilities.invokeLater(..)從RMI線程調用必須與使用sun.awt.SunToolkit.invokeLaterOnAppContext(..,..),如自定義invokeLater2(Runnable rn)方法代替不幸的是,所有來自RMI線程的SwingUtilities.invokeLater(..)的調用都必須替換,程序現在取決於內部的Sun JRE專有API。

我希望Oracle能儘快爲JRE 1.7.0.u25提供補丁來解決這個問題。

- 此替代方法是根據guruman的建議在評論here中進行的。

+0

1)我必須使用java 5編譯我的代碼,當我嘗試使用sun.awt.SunToolkit.invokeLaterOnAppContext時,它給了我錯誤,這是在Java 5之後添加的東西嗎? 2)我試過創建一個線程屬於一個特定的線程組,它的工作,但我真的不能使用這種方法,因爲我最終會創建大量的線程。 2。1)有沒有一種方法可以創建單個線程併爲其分配任務 2.2)有沒有辦法將任務分配給EDT,而無需使用invokeLater和invokeAndWait – user1216750

+0

實際上我使用java 1.7.0 Update 21。不要檢查以前的Java版本的代碼。這是我個人不喜歡使用內部JRE類的原因。 –

1

我與運行Java Web Start的Java3D有同樣的問題。我找到了另一個解決方案。你必須準備好你自己的帶有可運行隊列的InvokeLaterProcessor。它必須擴展Thread和挑選UPS可運行和運行方法對其進行處理:

public class InvokeLaterProcessor extends Thread { 

    private BlockingQueue<Runnable> queue=new ArrayBlockingQueue<Runnable>(1); 

    public InvokeLaterProcessor(String name) { 
    super(name); 
    } 

    public void invokeLater(Runnable runnable) { 
    try { 
     queue.put(runnable); 
    } catch (InterruptedException ex) { 
     log.warn("invokeLater interrupted"); 
    } 
    } 

    public void run() { 
    Runnable runnable=null; 
    do { 
     try { 
     runnable = queue.take(); 
     SwingUtilities.invokeLater(runnable); 
     } catch (InterruptedException ex) { 
     runnable=null; 
     } 
    } while(runnable!=null); 
    } 
} 

比所有你所要做的就是在靜態一些類,這是在主線程創建的創建:

static { 
    invokeLaterProcessor=new InvokeLaterProcessor("MyInvokeLater"); 
    invokeLaterProcessor.start(); 
} 

和過程可運行這段代碼:

invokeLaterProcessor.invokeLater(runnable); 

你不需要專有

sun.awt.SunToolkit.invokeLaterOnAppContext(evtContext, rn) 
0

下面是JDK-8019274的解決方法,打包在實用程序類中。

對我們而言,invokeAndWait()是個大問題。此示例具有用於invokeLater()的 現有修補程序和用於invokeAndWait()的新修復程序。

注:

  • 你需要jnlp.jar
  • 呼叫init()main()方法早,呼籲invokeLater()之前!
  • 所有呼叫這些電話

替換爲invokeLater()invokeAndWait()(免責聲明:這是從我們的產品該解決方案的某些方面可能對您不適用)

public class JreFix { 
    private static String badVersionInfo = null; 
    private static AppContext awtEventDispatchContext = null; 
    private static AppContext mainThreadContext = null; 
    private static Boolean isWebStart = null; 
    private static BasicService basicService = null; 
    private static IntegrationService integrationService = null; 

    /** 
    * Call this early in main(). 
    */ 
    public static void init() { 
     if (isWebstart() && isApplicableJvmType()) { 
      String javaVersion = System.getProperty("java.version"); 

      if ("1.7.0_25".equals(javaVersion)) { 
       badVersionInfo = "7u25"; 
      } 
      else if ("1.7.0_40".equals(javaVersion)) { 
       badVersionInfo = "7u40"; 
      } 
      else if (javaVersion != null && "1.6.0_51".equals(javaVersion.substring(0,8))) { 
       badVersionInfo = "6u51"; 
      } 
      else if ("javaws-10.25.2.16".equals(System.getProperty("javawebstart.version"))) { 
       badVersionInfo = "Web Start 10.25.2.16"; 
      } 
     } 

     if (badVersionInfo != null) { 
      mainThreadContext = AppContext.getAppContext(); 
      try { 
       SwingUtilities.invokeAndWait(new Runnable() { 
        public void run() { 
         awtEventDispatchContext = AppContext.getAppContext(); 
        } 
       }); 
      } 
      catch (Exception e) { 
       displayErrorAndExit(null); 
      } 

      if (mainThreadContext == null || awtEventDispatchContext == null) { 
       displayErrorAndExit(null); 
      } 
     } 
    } 

    public static void invokeNowOrLater(Runnable runnable) { 
     if (hasAppContextBug()) { 
      invokeLaterOnAwtEventDispatchThreadContext(runnable); 
     } 
     else { 
      SwingUtilities.invokeLater(runnable); 
     } 
    } 

    public static void invokeNowOrWait(Runnable runnable) { 
     if (hasAppContextBug()) { 
      fixThreadAppContext(null); 
     } 

     try { 
      SwingUtilities.invokeAndWait(runnable); 
     } 
     catch (Exception e) { 
      // handle it 
     } 
    } 

    public static boolean hasAppContextBug() { 
     return isJreWithAppContextBug() && AppContext.getAppContext() == null; 
    } 

    public static void invokeLaterOnAwtEventDispatchThreadContext(Runnable runnable) { 
     sun.awt.SunToolkit.invokeLaterOnAppContext(awtEventDispatchContext, runnable); 
    } 

    public static void fixThreadAppContext(Component parent) { 
     try { 
      final Field field = AppContext.class.getDeclaredField("threadGroup2appContext"); 
      field.setAccessible(true); 
      Map<ThreadGroup, AppContext> threadGroup2appContext = (Map<ThreadGroup, AppContext>)field.get(null); 
      final ThreadGroup currentThreadGroup = Thread.currentThread().getThreadGroup(); 
      threadGroup2appContext.put(currentThreadGroup, mainThreadContext); 
     } 
     catch (Exception e) { 
      displayErrorAndExit(parent); 
     } 

     if (AppContext.getAppContext() == null) { 
      displayErrorAndExit(parent); 
     } 
    } 

    private static boolean isJreWithAppContextBug() { 
     return badVersionInfo != null; 
    } 

    private static void displayErrorAndExit(Component parent) { 
     JLabel msgLabel = new JLabel("<html>" + 
       "Our application cannot run using <b>Web Start</b> with this version of Java.<p><p>" + 
       "Java " + badVersionInfo + " contains a bug acknowledged by Oracle (JDK-8019274)."); 
     JOptionPane.showMessageDialog(parent, msgLabel, "Java Version Error", JOptionPane.ERROR_MESSAGE); 
     System.exit(1); 
    } 

    private static boolean isApplicableJvmType() { 
     String vendor = System.getProperty("java.vendor"); 
     String vmName = System.getProperty("java.vm.name"); 
     if (vendor != null && vmName != null) { 
      return vmName.contains("Java HotSpot") && 
        (vendor.equals("Oracle Corporation") || 
        vendor.equals("Sun Microsystems Inc.")); 
     } 

     return false; 
    } 

    private static boolean isWebstart() { 
     if (isWebStart == null) { 
      try { 
       basicService = (BasicService) ServiceManager.lookup("javax.jnlp.BasicService");    
       isWebStart = true; 
      } 
      catch (UnavailableServiceException e) { 
       isWebStart = false; 
      }   

      try { 
       integrationService = (IntegrationService) ServiceManager.lookup("javax.jnlp.IntegrationService"); 
      } 
      catch (UnavailableServiceException e) { 
      } 
     } 
     return isWebStart; 
    } 
}