![](/img/trans.png)
[英]Thread-safety / reusability / life-span of AmazonDynamoDBClient?
[英]Life-span of JDI mirrors of objects living in a remote JVM
我一直在编写一个Java客户端,该客户端使用JDI在远程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
的镜像甚至可能会被垃圾回收ObjectReference.disableCollection()
无论如何,出于其他原因,我不想采取此步骤)。
所以我的问题是 ,是否有任何关于JDI Value
的书面寿命保证?
VirtualMachine
. mirror*()
方法文档什么也没说。) ObjectReference
进行GC,除非您之前设法禁用了它? 在此先感谢您的帮助!
尽管我找不到从我想要的角度来解决问题的任何文档,但是结合使用GrepCode上的com.sun.tools.jdi
包的源代码和Oracle网站上的JDWP协议规范,我得出以下结论: :
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
的构造函数或其任何超类的构造函数一直到MirrorImpl
都没有做任何会通过JDWP传输传输数据并因此更改服务器JVM状态的事情。
与#2对比。 JDI JavaDoc的出发点是任何ObjectReference
的镜像对象都可以在任何时间进行垃圾回收:
上的任何方法
ObjectReference
或直接或间接花费ObjectReference
作为参数可能抛出ObjectCollectedException
如果镜像对象是否已垃圾收集。
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);
}
可能对您有用的一件事是ObjectReference.disableCollection() ,它指示已调试的JVM从不收集该对象。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.