9

在工作中,我们发现在某些情况下(尤其是速度较慢的情况)我们有不同的行为,在重新启动时获得。

我们猜测缓存没有正确初始化,或者可能是并发问题......无论如何,它在生产之外的任何其他环境中都不可复制。

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

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

谢谢!

编辑:

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

编辑2:

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

编辑3:

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

Edit4: 经过一些经验,我真的很喜欢 VisualVM 之类的工具。还使用了YourKit。有一些有用的功能,例如 OQL,可以找到您需要查看的正确实例...

4

3 回答 3

8

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

于 2010-05-11T17:32:12.927 回答
4

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

您还可以使用 jmap 对整个堆进行堆转储,并且使用它(和 jhat),您可以看到对象关系(即什么对象指向什么),但不一定是对象内容。

当然,数据在堆转储中,它不是“点击离开”可见的。

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

否则,您最好向应用程序添加一些特定的工具,以提供您正在寻找的特定自省,由自定义代码、JMX 或其他触发。

于 2010-05-11T17:14:22.803 回答
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)这意味着您可以访问对象上的私有字段和方法。这是非常危险的- 仅在绝对必要时使用。

于 2010-05-11T17:13:59.560 回答