我们最近从Update 21更新到Java 7 Update 25,并且当从rmi线程调用SwingUtilities.isEventDispatchThread()时,现在遇到空指针异常,因为AppContext.getAppContext()返回null。
java.lang.NullPointerException at sun.awt.SunToolkit.getSystemEventQueueImplPP(未知来源)at sun.awt.SunToolkit.getSystemEventQueueImplPP(未知来源)at sun.awt.SunToolkit.getSystemEventQueueImpl(未知来源)at java.awt.Toolkit.getEventQueue(未知来源)at java.awt.EventQueue.isDispatchThread(未知来源)at javax.swing.SwingUtilities.isEventDispatchThread(未知来源)at ... ... at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)at sun.reflect.NativeMethodAccessorImpl.invoke(未知来源)at sun.reflect.DelegatingMethodAccessorImpl.invoke(未知来源)at java.lang.reflect.Method.invoke(未知来源)at sun.rmi.server.UnicastServerRef.dispatch(未知来源)at sun.rmi.transport.Transport $ 1.run(未知来源)at sun.rmi.transport.Transport $ 1.run(未知来源)at java.security.AccessController.doPrivileged(Native Method)at sun.rmi.transport.Transport.serviceCall(未知来源)at sun.rmi.transport.tcp.TCPTransport.handleMessages(未知来源)at sun.rmi.transport.tcp.TCPTransport $ ConnectionHandler.run0(未知 来源)at sun.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 :(得分:1)
我遇到了与Java Web Start一样运行的Java3D的问题。我找到了另一个解决方案。您必须使用runnables队列准备自己的InvokeLaterProcessor。它必须扩展Thread并获取runnables并在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();
}
并通过以下代码处理runnable:
invokeLaterProcessor.invokeLater(runnable);
您不需要专有
sun.awt.SunToolkit.invokeLaterOnAppContext(evtContext, rn)
答案 1 :(得分:0)
这不是最终答案,但它是一种解决方法,对我有用。
应用程序需要在EVT中保存当前的AppContext:
AppContext evtContext; //field
SwingUtilities.invokeLater(new Runnable() {
public void run() {
evtContext = AppContext.getAppContext();
}
});
然后,必须使用SwingUtilities.invokeLater(..)
的自定义invokeLater2(Runnable rn)
方法替换来自RMI线程的所有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提供补丁来解决这个问题。
-
此解决方法是根据评论here中guruman
的建议进行的。
答案 2 :(得分:0)
以下是JDK-8019274的解决方法,打包在实用程序类中。
对我们来说,invokeAndWait()
是个大问题。这个例子有
invokeLater()
的现有修正和invokeAndWait()
的新修补。
注意:
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;
}
}