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

Java 远程JVM中对象的JDI镜像的生命周期,java,garbage-collection,jvm,jdi,jdwp,Java,Garbage Collection,Jvm,Jdi,Jdwp,我一直在编写一个Java客户机,它用于在远程JVM中创建和修改对象(通过连接到远程JVM中运行的基于代理的服务器)。我的项目的一个要求是,我不能挂起远程JVM中的所有线程,这意味着我创建的对象在我能够在JVM中访问之前可能会受到垃圾收集的影响 在某些情况下,我在远程JVM中创建对象,但它们被随机垃圾收集。例如,如果我通过在远程JVM中创建一个数组,有时在我可以从远程JVM中的另一个可访问对象“可访问”之前,该数组将被垃圾收集 (例如,如果我试图将新数组存储到现有可访问对象的字段中,对的调用可能会

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

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

(例如,如果我试图将新数组存储到现有可访问对象的字段中,对的调用可能会随机抛出。):

从理论上讲,
ObjectReference
的镜像甚至可能在我能够调用之前被垃圾收集(这是出于其他原因我不想采取的步骤)

所以我的问题是,JDI
s上是否有记录在案的寿命保证

  • 在远程JVM中,原语值的镜像是否免于GC?(有人假设是这样,但是
    .mirror*()
    方法文档中没有一个能说明任何问题。)
  • a是否免于GC?(人们可能会认为不是,但JavaDoc似乎是沉默的。)
  • 我假设任何其他
    ObjectReference
    都可以在任何时候进行GC,除非您以前在它上面禁用了GC

提前感谢您的帮助

尽管我找不到任何文档能够准确地从我想要的角度来解决问题,但是结合查看上的
com.sun.tools.jdi
包的源代码,我得出以下结论:

  • “镜像”原语值永远不会消亡,因为在需要使用JDWP协议将其传输到服务器之前,整个原语值都存在于JDI客户机中。(在任何情况下,保留仅存在于服务器中的基元值的句柄都没有好处,因为通过传输发送句柄所需的字节数与仅发送基元值所需的字节数相同!)
  • 任何引用类型的镜像,包括对由创建的
    字符串的引用,都可以随时进行垃圾收集
  • 作为对#1的支持,请参见源代码示例:它只是实例化了
    LongValueImpl
    的一个新实例,并返回:

    public LongValue mirrorOf(long value) {
        validateVM();
        return new LongValueImpl(this,value);
    }
    
    您可以看到,无论是
    LongValueImpl
    的构造函数,还是它的任何超类的构造函数,一直到
    MirrorImpl
    都不会通过JDWP传输传输数据,从而改变服务器JVM的状态

    与#2形成对比。中的起点是可以随时对任何
    ObjectReference
    的镜像对象进行垃圾收集:

    ObjectReference
    上的任何方法,或直接或间接采用
    ObjectReference
    作为参数,如果 镜像对象已被垃圾回收

    这一点得到了源代码的证实,它与服务器中的JDWP代理通信。这只是确认,与任何
    ObjectReference
    a
    StringReference
    一样,以这种方式创建的
    a在任何时候都容易受到GC的影响,包括立即

    public StringReference mirrorOf(String value) {
        validateVM();
        try {
            return (StringReference)JDWP.VirtualMachine.CreateString.
                process(vm, value).stringObject;
        } catch (JDWPException exc) {
            throw exc.toJDIException();
        }
    }
    
    因此,据我所知,如果您有任何
    ObjectReference
    ,您需要在捕获
    ObjectCollectedException
    的循环中保护与远程JVM中镜像对象交互的所有尝试,除非远程JVM中的所有线程都挂起。例如,如果您的JDI客户机中有一个方法在远程JVM中创建一个
    字符串
    ,并返回一个不可垃圾回收的引用,那么您可以按照以下方式执行操作:

    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);
    }
    
    StringReference-safeStringRef(虚拟机虚拟机,字符串){
    ObjectCollectedException lastCause=null;
    对于(整数位数=0;整数位数
    一件可能对您有用的事情是,它向调试过的JVM发出信号,表示永远不要收集该对象。

    谢谢,这确实帮助了我!:)
    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);
    }