0

我有一个 java 进程,它每 10 毫秒连续创建一个短暂的线程和一个短暂的直接字节缓冲区,这会占用系统内存。尽管字节缓冲区是短暂的,但它们并没有得到清理。我根导致了这个问题并添加了 maxDirectMemorySize 并且也添加maxCacheBufferSize了,尽管它仍然表现出相同的行为。是因为maxCacheBufferSize? 我的意思是每个线程都在分配一个直接内存,相当于maxCacheBufferSize

-XX:MaxDirectMemorySize=256M
-Djdk.nio.maxCachedBufferSize=262144


while(true) {
        for (int i=0; i<100; i++) {
            es.execute(() -> {
                try {
                    ByteBuffer buffer = ByteBuffer.allocateDirect(2048);
                    Thread.sleep(10);
                } catch (InterruptedException ex) {
                    ex.printStackTrace();
               }
            });
    }
4

1 回答 1

1

在 Java 堆上,直接字节缓冲区是一个非常小的对象,它只有一个指向本机数组的指针......

随着 Java 堆满了,GC 会清理那些小对象,当这些小对象被清理干净时,原生数组就会被释放......

但是要填满 Java 堆需要很多这些非常小的对象。如果与您在系统堆上使用的内存量相比,您在 Java 堆上使用的内存量很小,那么这些本机数组可能会停留很长时间并占用大量系统内存。

你不应该有一堆短命的直接分配缓冲区。您可能应该只使用堆分配的缓冲区,或者回收直接分配的缓冲区,以便可以重用它们而不是分配新的缓冲区。

于 2019-09-09T03:24:42.407 回答