0

如何从另一个 JVM 加载 JVM 中现有的类对象?

我正在分析我的服务器中的一个罕见场景。我的服务器中没有正确的日志来帮助我解决这种情况,我相信这可能是特定类对象(用户定义)的问题。

比如说下面是这个类:

public class MyRequest 
{
  public byte[] getData()
  {
    return somdata;
  }
}

目前在我服务器的 JVM 中,100 个上述类对象在我的 JVM 内存中。我想知道是否有可能加载所有 100 个对象并访问它们的数据/方法(getData())。我不想创建 MyRequest 类的新实例(我知道这很容易)。我想通过另一个 Java 进程从我的 JVM 加载现有对象。

PS:我不能以任何理由杀死我的服务器。PS:我不能安装任何工具,比如visualvm等,更多的工具告诉我们对象类型、内存而不是确切的数据。

4

4 回答 4

2

基本上,它不会起作用。

  1. 如果你不能附加调试器,你就什么也做不了。

  2. 如果您可以附加一个调试器,您应该能够找到并查看这些实例,但是您将无法让它们做一些他们不打算做的事情。特别是,如果它们不是设计为可序列化的,您将无法序列化它们。

我认为您最好的选择是更改您的服务器代码以改进日志记录,然后使用调试器代理重新启动它......并等待问题再次出现。

当然,如果您连接了调试器,则无需将对象移动到另一个 JVM。您可以直接查看它们的状态。


但是,有一个问题。许多“非常罕见”的场景实际上与线程、线程安全和计时问题有关。你可以做很多事情来观察这样一个错误的影响,这很可能会改变程序的行为。


跟进

所以如果我们知道那个 JVM 的虚拟内存的起始地址……我们能不知道数据吗?假设所有对象都在 JVM 内存空间内。

它不是那么简单:

  • Java 堆上对象的位置是不可预测的。
  • 线程堆栈的位置是不可预测的。
  • 等等。

理论上可以转储任意进程的内存,重构JVM的执行状态,“读取”对象的状态。但是您需要专门的工具和/或大量的 JVM 内部知识才能做到这一点。我什至不确定这些工具是否存在......

简而言之,它不实用,AFAIK。

于 2013-07-12T12:44:18.973 回答
1

对象及其引用(别名)绑定到当前运行的 JVM。不可能在多个 JVM 之间共享它们。

如果要在两个 JVM 之间“共享”数据,则必须序列化这些数据,这意味着将它们从 JVM 发送到另一个。这也要求其实例应序列化的类实现接口Serializable。请注意,数组会自动实现 Serializable

您可以自己使用套接字、输出和输入流(这很费力)流式传输这些可序列化对象,也可以使用RMI调用远程方法并仅流式传输数据。在任何一种情况下,所有对象都会被复制并在另一个 JVM 中重新构建。没有机会分享它们。

在应用程序服务器的情况下,RMI 调用通常仅通过使用 EJB 来调用。但是你需要一个应用服务器;仅使用 Web 服务器是不够的。

于 2013-07-12T09:02:55.547 回答
1
Load existing class objects in JVM from another JVM

这是不可能的

于 2013-07-12T09:38:11.873 回答
0

请注意,您可以告诉 JVM 将其状态(使用终止信号或类似信号)转储到磁盘,以便您可以使用 post-Mortem 工具来分析程序的状态。

关键字是“core”和“hprof”,我自己还没有这样做。

于 2014-03-02T07:49:25.693 回答