如何在Java中固定字节数组?

时间:2009-07-11 03:58:29

标签: java arrays memory-management garbage-collection

有没有办法在java中固定一个字节数组,所以永远不会被移动/压缩?

我正在开发一个应用程序,它在运行时期间会有零GC,我想使用固定到内存映射区域的原始字节数组。有没有办法做到这一点或破解我的方式?

5 个答案:

答案 0 :(得分:6)

你可以使用ByteBuffer / allocateDirect()这会创建一个位于“c”空间的字节缓冲区,不会使用堆,因此它不会被移动,可以有效地用于JNI调用。

答案 1 :(得分:5)

真正零垃圾收集?真?

如果是这样,我会建议两种选择之一:

  1. 使用real-time JVM。几乎可以管理将一般应用程序与软实时系统分离的所有内容。
  2. 非常认真地考虑分配比特定运行期间所需内存更多的内存。这不是一个复杂的解决方案,但如果你有可用的内存,尝试分配比你预期的核心足迹多10倍的内存。它可能只是工作,你必须承认,RAM比软件工程人员便宜。
  3. 编辑很久以后:

    我刚想到您应该考虑静态分配字节数组。即,像这样:

    /** 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

Copying and Pinning

<块引用>

... 在调用 ReleasePrimitiveArrayCritical 之前,本机代码不应运行很长时间。 ... 不得调用其他 JNI 函数,或任何可能导致当前线程阻塞并等待另一个 Java 线程的系统调用。

...即使虚拟机不支持固定。

GetPrimitiveArrayCritical

对于您描述的应用程序,使用共享内存,您可能会考虑根本不使用 Java 数组,而是使用 JNI 更直接地访问资源。