7

最近、Update 21 から Java 7 Update 25 に更新しましたが、AppContext.getAppContext() が null を返すため、rmi スレッドから SwingUtilities.isEventDispatchThread() が呼び出されると、null ポインター例外が発生するようになりました。

java.lang.NullPointerException での sun.awt.SunToolkit.getSystemEventQueueImplPP (不明なソース) での sun.awt.SunToolkit.getSystemEventQueueImplPP (不明なソース) での sun.awt.SunToolkit.getSystemEventQueueImpl(不明なソース) での java.awt.Toolkit.getEventQueue( java.awt.EventQueue.isDispatchThread(不明なソース) で javax.swing.SwingUtilities.isEventDispatchThread(不明なソース) ... ... で sun.reflect.NativeMethodAccessorImpl.invoke0(ネイティブメソッド) で sun.reflect .NativeMethodAccessorImpl.invoke (未知のソース) で sun.reflect.DelegatingMethodAccessorImpl.invoke (未知のソース) で java.lang.reflect.Method.invoke (未知のソース) で sun.rmi.server.UnicastServerRef.dispatch (未知のソース) で sun. .rmi.transport.Transport$1.run (不明なソース) が sun.rmi.transport.Transport$1 にあります。Sun.rmi.transport.tcp.TCPTransport.handleMessages (未知のソース) で sun.rmi.transport.Transport.serviceCall (未知のソース) で java.security.AccessController.doPrivileged (ネイティブ メソッド) で (未知のソース) を実行します。 rmi.transport.tcp.TCPTransport$ConnectionHandler.run0 (不明なソース) で sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run (不明なソース) で java.util.concurrent.ThreadPoolExecutor.runWorker(不明なソース) で java. util.concurrent.ThreadPoolExecutor$Worker.run(不明なソース) で java.lang.Thread.run(不明なソース)run0 (未知のソース) で sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run (未知のソース) で java.util.concurrent.ThreadPoolExecutor.runWorker (未知のソース) で java.util.concurrent.ThreadPoolExecutor$Worker.run( java.lang.Thread.run(不明なソース) の不明なソース)run0 (未知のソース) で sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run (未知のソース) で java.util.concurrent.ThreadPoolExecutor.runWorker (未知のソース) で java.util.concurrent.ThreadPoolExecutor$Worker.run( java.lang.Thread.run(不明なソース) の不明なソース)

このエラーは Web Start からのみ発生します。IDE を介してアプリケーションを実行すると問題ありません。

他の誰かがこれに遭遇しましたか?AppContext に関する最新の更新で何が変更されたかについて何か考えはありますか?

更新後にAppContextに関連する問題が他の人に発生しているようです: https://forums.oracle.com/message/11077767#11077767

4

3 に答える 3

1

Java Web Start として実行されている Java3D でも同じ問題がありました。私は別の解決策を見つけました。ランナブルのキューを使用して、独自の InvokeLaterProcessor を準備する必要があります。Thread を拡張して runnable を取得し、それらを 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);
  }
}

あなたがしなければならないのは、メインスレッドで作成されたいくつかのクラスの静的に作成することだけです:

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

次のコードでランナブルを処理します。

invokeLaterProcessor.invokeLater(runnable);

独自のものは必要ありません

sun.awt.SunToolkit.invokeLaterOnAppContext(evtContext, rn)
于 2013-08-01T14:42:48.210 に答える
0

これは最終的な答えではありませんが、私にとってはうまくいく回避策です。

アプリケーションは現在の AppContext を EVT に保存する必要があります。

  AppContext evtContext; //field

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

次に、RMI スレッドからのすべての呼び出しを、次のようなカスタムメソッドSwingUtilities.invokeLater(..)に置き換える必要があります。invokeLater2(Runnable rn)sun.awt.SunToolkit.invokeLaterOnAppContext(..,..)

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

残念ながら、RMI スレッドからの SwingUtilities.invokeLater(..) へのすべての呼び出しを置き換える必要があり、プログラムは内部 Sun JRE 独自の API に依存するようになりました。

この問題に対処するために、オラクルが JRE 1.7.0.u25 のパッチをすぐに提供してくれることを願っています。

- この回避策は、ここgurumanのコメントからの提案に基づいて作成されました。

于 2013-06-25T15:39:08.273 に答える
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;
    }
}
于 2013-09-27T15:12:26.003 に答える