当前位置: 首页 > 知识库问答 >
问题:

AppContext是null从rmi线程Java7更新25

颛孙建业
2023-03-14

我们最近从Update 21更新到Java7 Update 25,现在遇到一个空指针异常,当SwingUtilities.isEventDispatchThread()从rmi线程调用时,因为AppContext.getAppContext()返回null。

JAVAlang.NullPointerException位于sun。awt。SunToolkit。sun上的getSystemEventQueueImplPP(未知源)。awt。SunToolkit。sun上的getSystemEventQueueImplPP(未知源)。awt。SunToolkit。java上的getSystemEventQueueImpl(未知源)。awt。工具箱。java上的getEventQueue(未知源)。awt。事件队列。javax上的isDispatchThread(未知源代码)。摆动勇气。isEventDispatchThread(未知源)位于。。。在太阳下。反映NativeMethodAccessorImpl。在sun上调用0(本机方法)。反映NativeMethodAccessorImpl。在sun上调用(未知源)。反映DelegatingMethodAccessorImpl。在java上调用(未知源)。朗。反思。方法在sun上调用(未知源)。马绍尔群岛共和国。服务器UnicastServerRef。太阳报的调度(未知来源)。马绍尔群岛共和国。运输交通费1美元。在sun上运行(未知源)。马绍尔群岛共和国。运输交通费1美元。在java上运行(未知源代码)。安全访问控制器。在sun的doPrivileged(本机方法)。马绍尔群岛共和国。运输运输sun上的serviceCall(未知源)。马绍尔群岛共和国。运输tcp。交通运输。sun上的handleMessages(未知源)。马绍尔群岛共和国。运输tcp。TCPTTransport$ConnectionHandler。在sun运行0(未知源)。马绍尔群岛共和国。运输tcp。TCPTTransport$ConnectionHandler。在java上运行(未知源代码)。util。同时发生的线程池执行器。java上的runWorker(未知源)。util。同时发生的线程池执行器$Worker。在java上运行(未知源代码)。朗。丝线。运行(未知源)

这个错误只在web开始时出现,当我们通过IDE运行应用程序时,就可以了。

还有其他人碰到过吗?关于AppContext的最新更新有什么变化吗?

更新后,其他人似乎与AppContext有一些相关的问题:https://forums.oracle.com/message/11077767#11077767

共有3个答案

贡正诚
2023-03-14

这里是JDK-8019274的一个变通方法,打包在一个实用程序类中。

对我们来说,调用和等待()是一个大问题。这个例子有一个的现有补丁,一个新的补丁,一个新的补丁,一个是调用程序()

注意事项:

  • 你需要jnlp。罐子
  • 调用invokeLater()之前,在main()方法的早期调用init()
  • 用这些调用替换对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;
    }
}

金坚
2023-03-14

这不是一个最终的答案,但它是一个变通办法,对我来说是有效的。

应用程序需要在EVT中保存当前的AppContext:

  AppContext evtContext; //field

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

然后所有调用SwingUtilities.invoke从RMI线程必须替换为自定义的调用Later2(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);
    }
}

不幸的是,所有对SwingUtilities的呼吁。调用器(…)必须更换来自RMI的线程,该程序现在依赖于内部Sun JRE专有API。

我希望Oracle能很快为JRE 1.7.0. u25提供补丁来解决这个问题。

这个解决方法是根据guruman在这里的评论中提出的建议。

魏硕
2023-03-14

我在运行Java3D时遇到了与JavaWebStart相同的问题。我找到了另一个解决办法。您必须准备您自己的带有可运行队列的InvokeLaterProcessor。它必须扩展线程并拾取可运行项,并在运行方法中处理它们:

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)
 类似资料:
  • 我有一个带有一些线程的简单应用程序,我需要从一些线程更新SWING GUI(我正在使用Netbean)。 这是我需要更新的主要表单: 现在我有一些线程: 在其他班级,我有: 代码的每个部分都位于不同的文件(类)中。我如何在这里实现 Swing 工作人员,以便能够在我的主 GUI 窗体上显示文本?

  • 问题内容: 亲爱的大家,我遇到了挥杆相关的问题。由于违反公司政策,我无法共享代码,因此我将尽力解释该问题。 简而言之,我创建了一个扩展包含JLabel的JWindow的类。JLabel的文本是通过计时器对象随机更新的,该计时器对象使用scheduleAtFixedRate方法每50毫秒实例化一个TimerTask。JLabel中的值是通过在一个单独的线程(称为传输线程)中调用一个方法来检索的,该线

  • 在我的JavaFX应用程序中,我想显示来自后台线程的实时数据。有人知道如何从后台线程更新linechart吗?谢谢你。下面是一些示例代码。 TM的 预览图像 采样控制器 } 处理类。启动线程。 任务类。执行任务的线程类 主类 样品fxml

  • 我正在编写一个Android应用程序,它连接到蓝牙设备,读取设备发送的数据,将其添加到AChartEngine图形中,并在文本视图中显示数据。 我的Bluetooth代码与BluetoothChat示例代码中的线程实现非常相似(它与SDK一起提供)。我可以在LogCat中看到< code>ConnectedThread循环正在执行并因此获得新数据,但我的TextView在7行之后停止更新,图形间歇

  • 问题内容: 我有一个javafx应用程序和一个工作线程,通过来实现,它执行一个漫长的过程,即压缩并上传一组文件。 我已通过将任务进度连接到进度条。 除此之外,我想将有关正在处理的项目的详细状态报告到ui中。 也就是说,正在处理的文件的名称及其大小以及单个文件处理可能引起的任何错误。 用这些信息更新UI不能从工作线程中完成,最多我可以将其添加到同步集合中。 但是然后我需要一些事件来通知UI新数据可用

  • 我有一个javafx应用程序和一个通过实现的工作线程,它执行一个很长的过程,即压缩和上载一组文件。 我已通过将任务进度连接到进度条。 除此之外,我还希望将正在处理的项的详细状态报告到UI中。即正在处理的文件的名称及其大小和单个文件进程可能产生的任何错误。 不能从辅助线程中使用这些信息更新UI,最多只能将其添加到同步集合中。 但我需要一些事件来通知UI新数据可用。 javafx是否对此问题有特定的支