GC中的GC.AddMemoryPressure等效

时间:2011-07-16 09:42:53

标签: java memory-management garbage-collection java-native-interface

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

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

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

2 个答案:

答案 0 :(得分:5)

经过一些谷歌搜索后,我从IBM研究中心找到了good article

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

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

答案 1 :(得分:1)

我相信本机内存的分配超出了Java堆大小的范围。这意味着,您不必担心您的分配会使用-Xmx<size>保留的值远离您的内存。

话虽这么说,您可以使用ByteBuffer.allocateDirect()来分配缓冲区,并GetDirectBufferAddress从您的本机代码访问它。您可以使用-XX:MaxDirectMemorySize=<size>

控制直接内存堆的大小