2013-06-20 6 views
6

Niedawno zaktualizowaliśmy do wersji Java 7 Update 25 z aktualizacji 21 i mamy teraz wyjątek wskaźnika pustego, gdy wywoływana jest funkcja SwingUtilities.isEventDispatchThread() z wątku rmi, ponieważ AppContext.getAppContext () zwraca zero.AppContext ma wartość null z wątku rmi z Java 7 Update 25

java.lang.NullPointerException na sun.awt.SunToolkit.getSystemEventQueueImplPP (Unknown Source) w sun.awt.SunToolkit.getSystemEventQueueImplPP (Unknown Source) w sun.awt.SunToolkit.getSystemEventQueueImpl (Unknown Source) w java.awt.Toolkit.getEventQueue (Unknown Source) w java.awt.EventQueue.isDispatchThread (Unknown Source) w javax.swing.SwingUtilities.isEventDispatchThread (Unknown Source) w ... ... w sun.reflect.NativeMethodAccessorImpl.invoke0 (Native Method) at sun.reflect.NativeMethodAcce ssorImpl.invoke (Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke (Unknown Source) at java.lang.reflect.Method.invoke (Nieznane źródło) pod sun.rmi.server.UnicastServerRef.dispatch (Nieznane źródło) pod numerem sun.rmi.transport.Transport $ 1.run (nieznane źródło) pod numerem sun.rmi.transport.Transport $ 1.run (nieznane źródło) pod adresem java.security.AccessController.doPrivileged (metoda macierzysta) pod adresem sun.rmi .transport.Transport.serviceCall (Unknown source) na sun.rmi.transport.tcp.TCPTransport.handleMessages (Unknown source) w sun.rmi.transport.tcp.TCPTransport $ ConnectionHandler.run0 (nieznane Źródło) na słońcu .rmi.transport.tcp.TCPTransport $ ConnectionHandler.run (Un Wiadomo Source) na java.util.concurrent.ThreadPoolExecutor.runWorker (nieznane Źródło) na java.util.concurrent.ThreadPoolExecutor $ Worker.run (nieznane Źródło) na java.lang.Thread.run (Unknown Source)

Ten błąd występuje tylko w Internecie, gdy uruchamiamy naszą aplikację za pośrednictwem IDE, jest w porządku.

Czy ktoś inny wpadł na to? Czy wiesz, co zmieniło się w najnowszej aktualizacji dotyczącej AppContext?

Wydaje inni mają nieco podobnych problemów z AppContext po aktualizacji: https://forums.oracle.com/message/11077767#11077767

+0

nie mogę zapewnij rozwiązanie, ale mamy ten sam problem z aktualizacją Java 7 Update 25. Mamy aplikację opartą na Swing, która jest rozprowadzana i uruchamiana za pomocą Java Webstart. Działa również jako serwer RMI. Gdy przychodzące wywołanie RMI wywołuje EventQueue.isDispatchThread, otrzymujemy ten sam wyjątek: sun.awt.AppContext # getAppContext() wydaje się zwracać wartość null w tej sytuacji. To poważna regresja, która sprawia, że ​​Java 7 Update 25 jest bezużyteczna dla naszej aplikacji. Podczas próby zastosowania obejścia z błędu 4711515 otrzymujemy kolejny krok. Ale wtedy pojawia się problem Nullpointer w JNLPClassLoader.getPermissions ... – Holger

+0

Problem Nullpointer w JNLPClassLoader.getPermissons() jest wymieniony tutaj: http://stackoverflow.com/questions/17230773/java-7-update25-makes-our -java-web-start-application-fail-with-no-logging Jest coś poważnie złego w wydaniu aktualizacji ... – Holger

+0

Mamy prawdopodobnie podobny problem: . W naszej aplikacji klient działa również jako serwer RMI. –

Odpowiedz

0

Nie jest to ostateczna odpowiedź, ale jest to obejście, że pracuje dla mnie.

Aplikacja trzeba zapisać bieżący AppContext w EVT:

AppContext evtContext; //field 

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

Następnie wszystkie połączenia do SwingUtilities.invokeLater(..) z RMI wątków należy zastąpić niestandardowym invokeLater2(Runnable rn) sposobem stosującym sun.awt.SunToolkit.invokeLaterOnAppContext(..,..) jak:

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); 
    } 
} 

Niestety wszystkie połączenia do SwingUtilities.invokeLater (..) z wątków RMI muszą zostać zastąpione, a teraz program zależy od wewnętrznego zastrzeżonego API Sun JRE.

Mam nadzieję, że Oracle wkrótce dostarczy łatki dla JRE 1.7.0.u25, aby rozwiązać ten problem.

- To obejście zostało wykonane zgodnie z sugestiami od guruman w komentarzach here.

+0

1) Muszę skompilować mój kod za pomocą Java 5 i daje mi błąd, gdy próbowałem użyć sun.awt.SunToolkit.invokeLaterOnAppContext, było to coś, co zostało dodane po Java 5? 2) Próbowałem podejść do tworzenia wątku należącego do określonej grupy wątków i działało, ale nie mogę naprawdę korzystać z tego podejścia, ponieważ skończę tworzenie wielu wątków. 2.1) Czy istnieje sposób przypisywania do utworzenia pojedynczego wątku i przypisywania do niego zadań 2.2) Czy istnieje sposób przypisania zadań do EDT bez użycia invokeLater i invokeAndWait – user1216750

+0

Aktualnie używam java 1.7.0 Update 21. Zrobiłem nie sprawdzaj kodu w poprzednich wydaniach java. To jest powód, dla którego osobiście nie lubię używać wewnętrznych klas JRE. –

1

Miałem ten sam problem z uruchomieniem Java3D jako Java Web Start. Znalazłem inne rozwiązanie. Musisz przygotować własny InvokeLaterProcessor z kolejką runnables. Musi ona rozszerzyć wątek i pick ups runnables i przetwarzać je w metodzie run:

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); 
    } 
} 

niż wszystko, co musisz zrobić, to stworzyć go w statycznym jakiejś klasy, który jest tworzony w głównym wątku:

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

i proces runnables przez ten kod:

invokeLaterProcessor.invokeLater(runnable); 

nie trzeba zastrzeżonych

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

Oto sposób obejścia problemu dla JDK-8019274, zapakowany w klasę narzędzi.

Dla nas, invokeAndWait() był duży problem. Ten przykład ma istniejącą poprawkę dla invokeLater() i nową poprawkę dla invokeAndWait().

Uwagi:

  • musisz jnlp.jar
  • połączenia init() wcześnie w swojej metodzie main(), przed wywołaniem invokeLater()!
  • Wymień wszystkie połączenia do invokeLater() i invokeAndWait() z tych połączeń

(Uwaga:.. Jest to z naszym produktem Niektóre aspekty tego rozwiązania mogą nie mieć zastosowania do Ciebie)

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; 
    } 
} 
Powiązane problemy