9
java版本“1.5.0_14”
Java(TM) 2 运行时环境,标准版(内部版本 1.5.0_14-b03)
Java HotSpot(TM) 服务器虚拟机(内部版本 1.5.0_14-b03,混合模式)

我正在尝试调试一个 NullPointerException,因为我将引用传递给静态定义的字段。更具体地说,我在 Drools3 工作内存实例上设置了一个全局变量。

workingMemory.setGlobal("log", workingMemorieslog);

我的假设是静态定义字段的类正在被垃圾收集。(接收类必须使用 Wea​​kReference 或类似的东西,我真的不知道)

你会建议如何调试这个?我认为,如果我能准确地知道 JVM 的 GC 何时卸载类/类的实例,那么我可以缩小错误行为的原因。(如果不是事件的确切时间,至少可以表明确实发生了某些事情)。

谢谢你,马克西姆。

4

4 回答 4

10

要跟踪 GC 活动,请将其添加到 java 命令:

-verbose:gc -XX:+PrintGCTimeStamps -XX:+PrintGCDetails

您得到的 NPE 可能是您传递了空值。

于 2009-02-22T00:10:01.327 回答
2

为什么不将课程保留在内存中,然后看看它是否仍然发生,如果确实如此,那么您的问题就出在其他地方。如果不是,那么您知道问题在于垃圾收集。

于 2009-02-22T00:14:17.790 回答
1

事实证明,日食是这里的主要问题。

我会解释:

为了测试性能,我将我们的 webapp 包装在 main() 方法中。我们使用了大量的 3rd 方代码,即 Apache commons-pool。

事实证明,我们有多个版本的 jar 分布在项目(eclipse 项目)中。我使用这些项目的应用程序有 commons-pool-1.3,另一个项目有 commons-pool-1.2。

当使用 servlet 容器 (Tomcat6) 加载时,webapp 类加载器具有第一优先级,因此它总是加载 webapp 版本。当我使用 main() eclipse 启动应用程序时,将依赖的项目 jars 导出到当前项目中的 -classpath 中并不是很明智的行为。

冲突发生在 2 个版本的 commons-pool 之间,这导致了未定义的行为 - 在对象借用时,有时决定创建一个新对象。我没有查看实现代码,我认为这与 GenericKeyedObjectPool (有问题的类)持有的静态映射有关。因为创建了一个新实例,所以它确实包含对提到的全局的空引用。

我运气的解决方案相当简单,commons-pool 仅由我的 web 应用程序使用,因此我可以从所有引用的项目中删除它,否则我想我会尝试将它们全部升级到一个版本。如果我不能做任何一个,我真的不知道我会做什么。这是 eclipse 的一个非常奇怪的默认设置。

感谢您的阅读和帮助。

// ps. 3 days. That's the time I've spend on understanding what the hell I did wrong in my servlet replacement code. Turns out I'm not even the problem. :P

于 2009-02-22T16:23:16.883 回答
0

你有堆栈跟踪吗?

您是否尝试过进入“setGlobal”方法(假设您有代码)以查看发生了什么?

于 2009-02-22T00:06:09.637 回答