有没有办法在java中固定一个字节数组,所以永远不会被移动/压缩?
我正在开发一个应用程序,它在运行时期间会有零GC,我想使用固定到内存映射区域的原始字节数组。有没有办法做到这一点或破解我的方式?
答案 0 :(得分:6)
你可以使用ByteBuffer / allocateDirect()这会创建一个位于“c”空间的字节缓冲区,不会使用堆,因此它不会被移动,可以有效地用于JNI调用。
答案 1 :(得分:5)
真正零垃圾收集?真?
如果是这样,我会建议两种选择之一:
编辑很久以后:
我刚想到您应该考虑静态分配字节数组。即,像这样:
/** Byte arrays that you absolutely have to keep. */
public class KeepForever {
/** Note that I make no claims about thread safety in this simple example. */
public static byte [] keepMe = new byte[100];
};
// Much later in example code ....
/** This should always succeed. No worries about garbage collection. */
public void setMe(int index, byte newByte) {
// Admittedly, this defeats several principles of OOD but it makes
// the point about the syntax.
KeepForever.keepMe[index] = newByte;
}
答案 2 :(得分:1)
见https://highlyscalable.wordpress.com/2012/02/02/direct-memory-access-in-java/。要在不使用反射或将代码绑定到特定JVM的情况下使用它,您需要创建与现有数组相同长度和类型的数组,或者创建非数组对象的浅表副本。
答案 3 :(得分:0)
虽然它与直接内存映射无关,但仍然可引用的对象不会是GC。引用保持生效的任何内容都应该没问题。
答案 4 :(得分:0)
通过 JNI 支持一些“固定”,但它非常有限。它只能发生在 JNI 调用的上下文中,而不是跨越它们,并且不需要每个 JVM 实现都支持。
<块引用>GetPrimitiveArrayCritical
返回 Java™ 数组的直接堆地址,禁用垃圾收集,直到调用相应的 ReleasePrimitiveArrayCritical
。
... 在调用 ReleasePrimitiveArrayCritical 之前,本机代码不应运行很长时间。 ... 不得调用其他 JNI 函数,或任何可能导致当前线程阻塞并等待另一个 Java 线程的系统调用。
...即使虚拟机不支持固定。
对于您描述的应用程序,使用共享内存,您可能会考虑根本不使用 Java 数组,而是使用 JNI 更直接地访问资源。