【问题标题】:Can we view objects in the JVM memory?我们可以查看JVM内存中的对象吗?
【发布时间】:2011-02-18 06:17:51
【问题描述】:

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

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

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

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

谢谢!

编辑:

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

编辑2:

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

编辑3:

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

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

【问题讨论】:

  • 我不知道在没有某种指针/变量引用的情况下访问对象的方法。

标签: java caching jvm production-environment


【解决方案1】:

您是否有权访问对象的句柄/指针?如果是这样,您可以在调试模式下启动它,然后在 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) 表示您可以访问对象上的私有字段和方法。这是极其危险的 - 仅在绝对必要时才使用它。

【讨论】:

  • 我不认为 Eclipse 中的调试器是一种选择,因为“它在生产环境之外的任何其他环境中都不可复制。”
  • @Andrew Hubbs:我个人在生产环境中使用过Eclipse调试——你必须以调试模式启动系统,并将其设置为远程连接。那里有很多选择 - 这并不容易,但有可能。
  • 我们的服务器不在同一个城市,我不知道他们是否可以在调试模式下启动生产 weblogic,也不知道他们是否会给我通过隧道访问.. .
  • @Sebastien Lorber:我建议您使用@Will Hartung 的建议——您可以获得一个堆转储,然后使用建议的各种工具对其进行解析。仅供参考——我第一次看到远程调试会话时,也是针对另一个城市的服务器。这是可能的——但听起来堆转储对你来说是一个更好的选择。
  • 可以肯定的是,我实际上每天都在远程服务器上进行调试,但他们永远不会让我访问生产实例...
【解决方案2】:

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

【讨论】:

  • +1 for Eclipse MAT - imo 是目前最强大(免费)的堆可视化工具。强烈推荐,并且有很棒的插件可以以有趣的方式查看堆(例如,收集填充百分比!)。
【解决方案3】:

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

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

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

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

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

【讨论】:

  • +1 - 我不知道堆转储。一两个月前这对我来说真的很有用:)
  • 我们使用 java 1.5 是否可以在 1.5 jre 上使用 jmap?我只在 jdk6 上找到了 jmap,它无法与我的本地 jre 1.5 一起使用...
猜你喜欢
  • 1970-01-01
  • 2017-03-30
  • 2020-04-18
  • 1970-01-01
  • 1970-01-01
  • 2010-09-20
  • 2021-06-03
  • 2015-02-23
  • 1970-01-01
相关资源
最近更新 更多