如何安全地解决此Java上下文类加载器问题? [英] How can I safely solve this Java context classloader problem?

查看:112
本文介绍了如何安全地解决此Java上下文类加载器问题?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的数百名用户中只有一位用户无法启动我的Java桌面应用。只有三分之一的时间才开始。另外三分之二的时间在启动时抛出NullPointerException:

One and only one of my hundreds of users has trouble starting my Java desktop app. It only starts for him about one-third of the time. The other two-thirds of the time a NullPointerException is thrown at startup:

Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
    at java.util.Hashtable.put(Hashtable.java:394)
    at javax.swing.JEditorPane.registerEditorKitForContentType(JEditorPane.java:1327)
    at javax.swing.JEditorPane.registerEditorKitForContentType(JEditorPane.java:1309)
    at javax.swing.JEditorPane.loadDefaultKitsIfNecessary(JEditorPane.java:1387)
    at javax.swing.JEditorPane.getKitTypeRegistry(JEditorPane.java:1344)
    at javax.swing.JEditorPane.getEditorKitClassNameForContentType(JEditorPane.java:1340)
    at javax.swing.JTextPane.<init>(JTextPane.java:76)
    at myapp.Launcher$1.run(Launcher.java:13)
    at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:209)
    at java.awt.EventQueue.dispatchEvent(EventQueue.java:633)
    at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:296)
    at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:211)
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:201)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:196)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:188)
    at java.awt.EventDispatchThread.run(EventDispatchThread.java:122)

我跟着堆栈跟踪找到原因是

I've followed the stack trace to find that the cause is that

Thread.currentThread().getContextClassLoader()


$ JEdi​​torPane中的b $ b

返回null。

in JEditorPane is returning null.

谷歌搜索显示这是一个零星的,非常罕见且神秘的问题,影响了一些人。

Googling reveals that this is a sporadic, very infrequent, and mysterious problem that affects a few people.

我的问题是,我可以做什么作为解决方法?如果我在创建EditorPane之前调用它,这可能会有效:

My question is, what can I do as a work-around? This might work, if I call it before creating an EditorPane:

Thread.currentThread().setContextClassLoader(MyClass.class.getClassLoader());

但是我并不像我想的那样理解类加载器(我试过更好地理解他们)。我觉得改变EDT中的contextClassLoader可能会产生不良后果。

But I don't really understand classloaders as well as I would like (and I've tried to understand them better). I feel that changing the contextClassLoader in the EDT could have bad ramifications.

我能做些什么?

编辑:我和那些了解Java ClassLoaders的人有一些通信。这似乎是一个模糊的ClassLoader竞争条件。也就是说,Java中的一个错误。

I had some correspondence with someone who understands Java ClassLoaders well. It seems this is an obscure ClassLoader race condition. That is, a bug in Java.

推荐答案

Thread.currentThread().getContextClassLoader()

如果中的代码JEditorPane.registerEditorKitForContentType 不检查上面代码中的null返回值,这是 JEditorPane 中的错误。请注意 MyClass.class.getClassLoader() 也可能返回null 。唯一可以依赖的是系统类加载器

If the code in JEditorPane.registerEditorKitForContentType does not check for a null return value in the above code, this is a bug in JEditorPane. Note that MyClass.class.getClassLoader() may also return null. The only one you can rely on is the system ClassLoader.

为调用设置上下文 ClassLoader 的模式通常看起来类似这样的事情:

The pattern for setting the context ClassLoader for an invocation usually looks something like this:

Thread thread = Thread.currentThread();
ClassLoader old = thread.getContextClassLoader();
thread.setContextClassLoader(fooClassLoader);
try {
  // do call that depends on context ClassLoader
} finally {
  thread.setContextClassLoader(old);
}

应通过 setContextClassLoader设置的值将取决于使用它的代码的意图以及您正在运行的 ClassLoader 框架的设计。

The value that should be set via setContextClassLoader will depend on the intent of the code that is consuming it and the design of the ClassLoader framework you are running in.

在一个独立的应用程序中,你可能只需使用这个 ClassLoader (将ref传递给当前类):

In a stand-alone application, you can probably get away with just using this ClassLoader (passing in a ref to the current class):

private ClassLoader findClassLoaderForContext(Class<?> c) {
  ClassLoader context = Thread.currentThread().getContextClassLoader();
  ClassLoader me = c.getClassLoader();
  ClassLoader system = ClassLoader.getSystemClassLoader();
  return (context == null) ? (me == null) ? system : me : context;
}

在ClassLoader敏感的插件框架中(Java EE服务器将是一个主要的例子,它需要了解加载方案的性质和用法。

In a ClassLoader-sensitive plug-in framework (a Java EE server would be a prime example), it would pay to understand the nature and usage of the loading scheme.

这篇关于如何安全地解决此Java上下文类加载器问题?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆