什么';它是.net的Java等价物';s.G.KeepAlive?

什么';它是.net的Java等价物';s.G.KeepAlive?,java,.net,garbage-collection,java-native-interface,finalizer,Java,.net,Garbage Collection,Java Native Interface,Finalizer,.NET有一个名为的函数。它的唯一目的是确保被引用对象的生存期持续到代码流到达调用为止 除非与本机代码互操作,否则这通常是不必要的 我有一个情况,我有一个通过JNI访问的C++对象的图,其中某些根对象需要保存,以保持孩子们的生存。根对象和子对象在JVM区域中都有镜像。如果根对象被收集并释放在C++侧(通过SWIG生成的终结器),但是子对象将变得无效,因为它们的C++支持对象将被释放。 这可以通过确保作为对象图根的局部变量的生存期超过子对象的最后一次使用来解决。因此,我需要一个惯用函数,它对对象不

.NET有一个名为的函数。它的唯一目的是确保被引用对象的生存期持续到代码流到达调用为止

除非与本机代码互操作,否则这通常是不必要的

<>我有一个情况,我有一个通过JNI访问的C++对象的图,其中某些根对象需要保存,以保持孩子们的生存。根对象和子对象在JVM区域中都有镜像。如果根对象被收集并释放在C++侧(通过SWIG生成的终结器),但是子对象将变得无效,因为它们的C++支持对象将被释放。 这可以通过确保作为对象图根的局部变量的生存期超过子对象的最后一次使用来解决。因此,我需要一个惯用函数,它对对象不做任何操作,但不会被优化或移动(例如,从循环中提升)。这就是
GC.KeepAlive(Object)
在.NET中所做的

Java中的近似等价物是什么

PS:一些可能的说明性代码:

class Parent {
    long ptr;
    void finalize() { free(ptr); }
    Child getChild() { return new Child(expensive_operation(ptr)); }
}

class Child {
    long ptr;
    void doStuff() { do_stuff(ptr); }
}

// BAD CODE with potential for SIGSEGV
for (Parent p : getParents()) {
    p.getChild().doStuff();
}
问题在于GC释放父级p将在doStuff执行时释放分配给子级的内存。GC在实践中被观察到这样做。如果
GC.KeepAlive
可用,则可能会进行修复:

// BAD CODE with potential for SIGSEGV
for (Parent p : getParents()) {
    p.getChild().doStuff();
    GC.KeepAlive(p);
}
例如,我可以在p上调用
toString
,但我不会对其输出做任何操作。我可以在数组中临时插入p,但是我怎么知道JVM不会丢弃存储呢?等等。

我想你可以用JMH来做这个。它的设计目的是确保引用不会在基准测试中被消除,因此它应该可以工作


基本上,它只是将给定的对象引用与存储的易失性引用进行比较,并以较小的概率重新分配后者(存储成本很高,因此会最小化)。

每当垃圾回收器在调用本机方法时具有足够的攻击性来声明该对象时,而且在Java世界中,很少有人关心这样一个问题:要么问题不存在,要么周围有很多有缺陷的代码,这一点似乎为使用
GC.KeepAlive(Object)
提供了一个合理的选择,即使用非静态的本机JNI方法,合理地防止对调用这些方法的实例进行任何可能的垃圾收集。

我认为没有垃圾收集。Java的GC不在计时器上工作,至少据我所知,它遍历对象图,通常称为“标记和扫描”。我认为您只需在某个地方保留对所讨论对象的引用,GC会将它们标记为已使用,而不会在GC过程中清除它们;如果调用终结器,则意味着代码无法接触到此本机资源的持有者,因此释放它是正常的。如果您保留对它的引用(例如在instanceYes的池中),可以避免这种情况。我想做的就是保留对父(根)对象的引用。问题是,这个引用是本地的,需要保持在它所在的位置,即使我对引用不做任何处理。我担心优化会丢掉我的“无所事事”工作,因为它唯一的副作用就是禁用过早的定稿。我怀疑在这个阶段我会得到更好的答案,所以我给你打勾。