GC中的GC.AddMemoryPressure等效

项目:Java,JNI(C ++),Android。

我将通过创建一个托管包装类来管理本机C ++对象的生命周期,该类包含一个指向本机对象的指针(作为一个长成员),并将删除其中重写的finalize()方法中的本机对象。 有关详细信息,请参阅此问

C ++对象不消耗其他类型的资源,只消耗内存。 对象的内存占用量不是很高,但它基本上高于Java中64位的长度。 有没有办法告诉Java的GC,我的包装器不仅仅是一个很长的值,而且在运行垃圾收集之前创建数百万个这样的对象并不是一个好主意? 在.NET中有一个GC的AddMemoryPressure ()方法,正是出于这个目的。 Java中是否存在等价物?

经过一番谷歌搜索,我发现了IBM研究中心的一篇好文章 。

简而言之,他们建议对本机对象使用Java堆而不是本机堆。 这样,JVM垃圾收集器上的内存压力对于本机对象更加真实,从Java代码通过句柄引用。

要实现这一点,需要覆盖默认的C ++堆分配和释放function:operator new和operator delete。 在operator new中,如果JVM可用(已经调用了JNI_OnLoad),则调用NewByteArray和GetByteArrayElements,它返回所需的已分配内存。 为了保护创建的ByteArray不被垃圾收集,还需要为其创建一个NewGlobalRef,并将其存储在例如相同的已分配内存块中。 在这种情况下,我们需要分配尽可能多的内存,以及引用的内存。 在operator delete中,需要DeleteGlobalRef和ReleaseByteArrayElements。 如果JVM不可用,则使用本机malloc和free函数。

我相信本机内存是在Java堆大小范围之外分配的。 这意味着,您不必担心使用-Xmx从您保留的值中获取内存。

话虽这么说,您可以使用ByteBuffer.allocateDirect()来分配缓冲区和GetDirectBufferAddress来从您的本机代码访问它。 您可以使用-XX:MaxDirectMemorySize=来控制直接内存堆的-XX:MaxDirectMemorySize=