gpt4 book ai didi

Java 类加载器问题或并发错误?

转载 作者:行者123 更新时间:2023-11-30 03:42:05 33 4
gpt4 key购买 nike

WebLogic 应用程序正常运行几周后,我突然遇到异常:

<Oct 25, 2014 9:31:11 PM EDT> <Error> <HTTP> <BEA-101020>
<[ServletContext@60724164[app:whatever3000 module:whatever3000.war path:
spec-version:2.5]] Servlet failed with Exception
java.lang.ExceptionInInitializerError

此后,应用程序将因 NoClassDefFoundError 完全失效,直到应用程序服务器重新启动。

完整的堆栈跟踪显示问题的根源是静态初始化程序中的 ConcurrentModificationException

具体等效/最小化代码如下:

package a;
import b;

public class Whatever {
void doIt()
{
Password p = new Password();
}
}

package b;

public final class Password implements Serializable
{
private static final int PARAM1 = CommonStuff.someStaticMethod();
...
}

import java.util.Properties;

public class CommonStuff
{
private static Properties prp = new Properties();

static {
CommonStuff.load();
}

public static void load()
{
prp.putAll(System.getProperties()); <---FAIL

这是异常的由来:

java.util.ConcurrentModificationException
at java.util.Hashtable$Enumerator.next(Hashtable.java:1017)
at java.util.Hashtable.putAll(Hashtable.java:469)
at b.CommonStuff.load(CommonStuff.java:55)
at b.CommonStuff.<clinit>(CommonStuff.java:77)
at b.Password.<clinit>(Password.java:44)
at a.doIt(Whatever.java:99)

因此,在应用程序运行时的某个时刻,WebLogic 决定从包 b 重新加载类,但是当静态 block 运行时,它发现 Properties 对象已修改。

我不知道它是被同时调用还是被多次调用。可能是 Properties 对象是应用程序首次加载时创建的原始实例,并且重新加载 CommonStuff 类正在尝试调用 putAll()再次

如果我这样做会有帮助吗:

private static Properties prp = null;

static {
CommonStuff.prp = new Properties();
CommonStuff.load();
}

我不能盲目尝试,因为它是在一家大公司的生产应用程序中。因此,我试图了解我哪里出错了,以及如何在半夜重新加载类时对这些变量进行属性初始化。

有什么想法吗?

这可能是 WebLogic 类加载器问题吗?

最佳答案

在此类初始化之前,类/实例无法访问某些类的成员。因此,在静态构造函数返回之前,没有人可以访问新创建的 prp。将 prp 初始值设定项移动到 static {} block 内没有任何区别。另外,“旧”CommonStuff 中的“旧”prp 和"new"prp 没有以任何方式连接(因为“旧”和“new"CommonStuff 是 JVM 的不同类)。这一切都使得并发修改 prp 的可能性看起来非常奇怪。

我相信原因在另一个地方。请注意堆栈跟踪的第一行:HashtableEnumerator 引发异常。下面是 putAll 方法的代码(在 JDK 8 中,可能很多年都没有改变):

for (Map.Entry<? extends K, ? extends V> e : t.entrySet())
put(e.getKey(), e.getValue());

这里是抛出异常的 Enumerator - 它不是 prp,它是参数的 Enumerator

因此,异常与 prp 无关,而是与 System.getProperties() 返回的 Map 相关。原因是迭代系统属性映射不是线程安全的。似乎另一个线程正在同时修改它。

您需要以不同的方式初始化prp。我认为 clone() 是最简单的方法。

关于Java 类加载器问题或并发错误?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26610886/

33 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com