0

I have a java process which creates a short lived thread and a short live direct byte buffer in them continuously every 10 milliseconds which is eating up system memory. Though the byte buffers are short-lived, they are not getting cleaned up. I root caused the issue and added maxDirectMemorySize and also maxCacheBufferSize too, although it still exhibits the same behavior. Is it because of maxCacheBufferSize? I mean every thread is allocating a direct memory equivalent to 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();
               }
            });
    }
user3671657
  • 37
  • 1
  • 8

1 Answers1

2

On the Java heap, a direct byte buffer is a very small object that just has a pointer to the native array...

As the Java heap gets full, GC will clean up those small objects, and when those small objects get cleaned up, the native arrays will be freed...

But it takes a LOT of those very small objects to fill up the Java heap. If amount of memory you're churning through on the Java heap is small compared to the amount you're using on the system heap, then those native arrays can hang around a long time and eat up a lot of system memory.

You should just not have a bunch of short-lived direct-allocated buffers. You should probably just use heap-allocated buffers, or recycle the direct-allocated buffers so that they can be reused instead of allocating new ones.

Matt Timmermans
  • 53,709
  • 3
  • 46
  • 87
  • These small object originally in Eden space. If I remember correctly if they survived few GC cycle...they will be put in OldGen space of heap. When OldGen piling up to maximum and Eden space is full....then OutOfMemoryException. Again I stand to be corrected. – Awan Biru Sep 09 '19 at 03:29
  • 1
    That's essentially correct, but I'm not sure what your point is. Eden/Old gen, etc., are areas of the java heap and don't count the native arrays... which is the problem here. We don't have any information from the OP about how long these small objects are surviving on the java heap. – Matt Timmermans Sep 09 '19 at 03:36
  • Isn't adding MaxDirectMemorySize force GC when system memory reaches the value of maxDirectMemorySize? – user3671657 Sep 09 '19 at 03:46
  • Yes, if your JVM supports it. What did you set it to, and how much system memory is being eaten? – Matt Timmermans Sep 09 '19 at 04:10
  • @user3671657 even though you could force a GC...it does not mean those objects would be collected. If those objects are still referenced, it won't be collected. – Awan Biru Sep 09 '19 at 05:20
  • @marr timmermans I have setup my system memory to 256 mb and heap size is also 256mb. It is consuming almost 2gb of system memory and increasing every minute. The heap memory utilization is 25mb to 30 mb. I didnt get the part if my jvm supports the gc! How one figure out that? – user3671657 Sep 09 '19 at 15:21
  • @awanbiru I am sure those bytebuffer are not being referenced anywhere after the thread complete execution. The infinite while is there to exhibit the leak. – user3671657 Sep 09 '19 at 15:25