什么是.net的GC.KeepAlive的Java等价物?

Bar*_*lly 9 .net java java-native-interface garbage-collection finalizer

.NET有一个名为的函数GC.KeepAlive(Object).其唯一目的是确保引用对象的生命周期持续到代码流到达调用.

除非有人与本机代码进行互操作,否则通常不需要这样做.

我有一种情况,我有一个通过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();
}
Run Code Online (Sandbox Code Playgroud)

麻烦的是,在doStuff执行时,GC释放Parent p将释放为Child分配的内存.已经观察到GC在实践中这样做.GC.KeepAlive可用的潜在修复:

// BAD CODE with potential for SIGSEGV
for (Parent p : getParents()) {
    p.getChild().doStuff();
    GC.KeepAlive(p);
}
Run Code Online (Sandbox Code Playgroud)

我可以例如调用toStringp,但我不会对其输出做任何事情.我可以暂时将p戳到一个数组中,但我怎么知道JVM不会丢弃商店?等等.

maa*_*nus 2

我想你可以使用 JMH Blackhole来实现这一点。它的设计目的是确保参考不会在基准测试中被消除,因此它应该可以工作。

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