我们可以在JVM内存中查看对象吗?

时间:2010-05-11 17:10:03

标签: java caching jvm production-environment

在工作中我们发现在某些情况下(特别是慢速情况),我们会在重启时获得不同的行为。

我们猜测缓存未正确初始化,或者可能是并发问题...... 无论如何,它不能在任何其他环境中再生产。

我们实际上没有记录器来激活...它是一个旧组件......

因此,我想知道是否有工具可以帮助我们查看JVM内存中存在的不同对象,以便检查缓存的内容......

谢谢!

修改

我没有直接访问生产服务器,我们的app服务器是weblogic 10,我没有指向该对象的指针,但我知道缓存对象类型......

EDIT2:

我们的服务器在jre 1.5上运行,是否可以使用jmap?在jdk5中找不到它:( 此外,远程调试可能不错,但出于安全原因我们不能......

EDIT3:

实际上jhat + VisualVM对我来说没问题,我在转储中找到了我的对象,但是我无法正确读取hashmap(包含大约60000个项目的对象)... 是否有工具以友好的方式读取concurrenthashmap?我需要找到一个键的值(或它在地图中的存在),而无需手动浏览60k记录。 实际上我在eclipse MAT论坛上看到它也是不可能的......

Edit4: 经过一些经验,我真的很喜欢像VisualVM这样的工具。也用过YourKit。 有一些有用的功能,比如OQL,可以找到你需要查看的正确实例......

3 个答案:

答案 0 :(得分:7)

这基本上是为了扩展Will所说的内容。 通过让我们的管理员对我们的生产系统进行堆转换,我取得了很大的成功,但需要注意的是,在转储完成之前,您要转储的特定服务器将无响应。然后获取该文件并使用Eclipse MAT插件来查看它。如果你不喜欢Eclipse,也可以使用Netbeans和普通的VisualVM插件。这可能会创建一些大文件,您可能需要在64位系统上运行。

答案 1 :(得分:4)

运行jmap以转储COUNT个对象实例相当容易,但我不知道这是否是您真正感兴趣的内容。

你也可以使用jmap对整个堆进行堆转储,并使用它(和jhat),你可以看到对象RELATIONSHIPs(即什么对象指向什么),但不一定是对象CONTENTS。

当然,堆转储中存在数据,而不是“点击”可见。

我认为一些专业的分析器可以让你在堆转储中内省对象。

除此之外,您最好在应用程序中添加一些特定的工具,以提供您正在寻找的特定内省,由自定义代码,JMX或其他任何内容触发。

答案 2 :(得分:3)

您是否可以访问对象的句柄/指针?如果是这样,您可以在调试模式下启动它,并在Eclipse之类的调试器中查看它。这将允许您检查变量等。

或者,你可以编写一个小的记录器,反复地遍历课程并记录正在发生的事情。所有这些都假设您有一个位置,您可以开始进入代码,或者可以获得对缓存值的引用。


编辑:正如我在评论中提到的,我不知道如何在没有某种引用或引用链接的情况下访问对象。例如,对象是否封装在另一个对象中?如果是这样,您可以执行以下操作:

Class<?> objectClass = myPointer.getClass();
Field[] objectFields = objectClass.getDeclaredFields();
for (Field field : objectFields) {
    field.setAccessible(true);
    //Or whatever you would need to do to get the information you need
    System.out.println(field.get(myPointer).toString());
}

您还可以执行以下操作:

Field targetField = objectClass.getDeclaredField("myFieldName");
targetField.setAccessible(true);
MyOldObjectType target = (MyOldObjectType)targetField.get(myPointer);
//do whatever you need to do here

请注意,所有反射方法都会抛出异常,因此您需要根据需要处理这些异常。此外,setAccessible(true)表示您可以访问该对象上的私有字段和方法。这是非常危险 - 只有在必要时才使用它。

相关问题