最近在查一个内存泄露问题的时候查到的,总所周知-XX:MaxDirectMemorySize可以设置java堆外内存的峰值,但是具体是在哪里限制的呢
java.nio.DirectByteBuffer用于生成一块cap大小的堆外内存
java.nio.Bits
// These methods should be called whenever direct memory is allocated or // freed. They allow the user to control the amount of direct memory // which a process may access. All sizes are specified in bytes. static void reserveMemory(long size, int cap) { synchronized (Bits.class) { if (!memoryLimitSet && VM.isBooted()) { maxMemory = VM.maxDirectMemory(); memoryLimitSet = true; } // -XX:MaxDirectMemorySize limits the total capacity rather than the // actual memory usage, which will differ when buffers are page // aligned. if (cap <= maxMemory - totalCapacity) { //这里操作了totalCapacity,注意是加锁的哦 reservedMemory += size; totalCapacity += cap; count++; return; } } System.gc(); try { Thread.sleep(100);//其实jvm也用了很low的sleep下么 } catch (InterruptedException x) { // Restore interrupt status Thread.currentThread().interrupt(); } synchronized (Bits.class) { if (totalCapacity + cap > maxMemory) //这里超过就异常了 throw new OutOfMemoryError("Direct buffer memory"); reservedMemory += size; totalCapacity += cap; count++; } }
补充一下,计算totalCapacity的时候加了同步锁,所以申请堆外内存的时候也限制了服务性能。