gpt4 book ai didi

java - 远程 JVM 中对象的 JDI 镜像的生命周期

转载 作者:行者123 更新时间:2023-12-02 05:28:08 26 4
gpt4 key购买 nike

我一直在编写一个使用 JDI 的 Java 客户端在远程 JVM 中创建和修改对象(通过连接到在远程 JVM 中运行的 JDWP 基于代理的服务器)。我的项目的要求之一是我无法挂起远程 JVM 中的所有线程,这意味着我创建的对象在我使它们在 JVM 中可访问之前可能容易受到垃圾收集的影响。

在某些情况下,我在远程 JVM 中创建对象,但它们会被随机垃圾收集。例如,如果我通过 ArrayType.newInstance(int) 在远程 JVM 中创建一个数组,有时在我可以从远程 JVM 中的另一个可访问对象“访问”该数组之前,该数组将被垃圾收集。

(例如,如果我尝试将新数组存储到现有可访问对象的字段中,对 ObjectReference.setValue(Field, Value) 的调用可能会随机抛出 ObjectCollectedException):

void createAndStoreArray(ObjectReference reachableObj, Field fieldOfObj, ArrayType type, int length)
{
ArrayReference ref = type.newInstance(length);
reachableObj.setValue(fieldOfObj, ref); // Sometimes throws ObjectCollectedException because ref's mirror garbage gets collected before I can store it on the reachable object
}

理论上,在我能够调用 ObjectReference.disableCollection() 之前,ObjectReference 的镜像甚至可能会被垃圾收集。 (无论如何,由于其他原因,我不想采取这一步)。

所以我的问题是,JDI Value 是否有任何记录在案的使用生命周期保证?

  • 原始值的镜像是否在远程 JVM 中免于 GC? (有人认为是这样,但 VirtualMachine .mirror*() 方法文档都没有说明任何内容。)
  • mirror of a String豁免GC? (有人可能会认为不会,但 JavaDoc 似乎保持沉默。)
  • 我假设任何其他 ObjectReference 都可以随时进行 GC,除非您之前设法对其禁用 GC?

预先感谢您的帮助!

最佳答案

虽然我找不到任何从我想要的角度解决问题的文档,但结合查看 GrepCode 上的 com.sun.tools.jdi 包的源代码和 JDWP protocol spec on Oracle's website让我得出这样的结论:

  1. “镜像”原始值永远不会消失,因为整个原始值都存在于 JDI 客户端中,直到需要使用 JDWP 协议(protocol)将其传输到服务器为止。 (在任何情况下,保留仅存在于服务器中的原始值的句柄都没有优势,因为通过传输发送句柄需要与仅发送相同数量或更多的字节原始值!)
  2. 引用类型的任何镜像,包括对 VirtualMachine.mirrorOf(String) 创建的 String 的引用可以随时被垃圾收集。

作为对 #1 的支持,请参阅 com.sun.tools.jdi.VirtualMachineImpl.mirrorOf(long) 的源代码:它只是实例化 LongValueImpl 的新实例并返回:

public LongValue mirrorOf(long value) {
validateVM();
return new LongValueImpl(this,value);
}

您可以看到,LongValueImpl 的构造函数及其任何父类(super class)的构造函数一直到 MirrorImpl 都没有执行任何通过 JDWP 传输数据的操作传输,从而改变服务器 JVM 的状态。

与#2 对比。起点在JDI JavaDoc任何ObjectReference的镜像对象都可以随时被垃圾收集:

Any method on ObjectReference or which directly or indirectly takes ObjectReference as parameter may throw ObjectCollectedException if the mirrored object has been garbage collected.

com.sun.tools.jdi.VirtualMachineImpl.mirrorOf(String) 的来源证实了这一点,它与服务器中的 JDWP 代理进行通信。这只是确认像任何 ObjectReference 一样,以这种方式创建的 StringReference 随时都容易受到 GC 的影响,包括立即...

public StringReference mirrorOf(String value) {
validateVM();
try {
return (StringReference)JDWP.VirtualMachine.CreateString.
process(vm, value).stringObject;
} catch (JDWPException exc) {
throw exc.toJDIException();
}
}

据我所知,如果您有任何 ObjectReference ,您需要在捕获 的循环中保护与远程 JVM 中的镜像对象交互的所有尝试ObjectCollectedException 除非远程 JVM 中的所有线程都被挂起。例如,如果您的 JDI 客户端中有一个方法在远程 JVM 中创建一个 String 并返回对其的非垃圾可收集引用,您可以按照以下方式执行操作:

StringReference safeStringRef(VirtualMachine vm, String string) {
ObjectCollectedException lastCause = null;
for (int numTries = 0; numTries < SANE_TRY_LIMIT; ++numTries) {
StringReference stringRef = vm.mirrorOf(string);
try {
stringRef.disableCollection();
return stringRef;
} catch (ObjectCollectedException e) {
lastCause = e;
}
}
throw new RuntimeException("Can't create safe string reference", lastCause);
}

关于java - 远程 JVM 中对象的 JDI 镜像的生命周期,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25793688/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com