最近在查一个内存泄露问题的时候查到的,总所周知-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的时候加了同步锁,所以申请堆外内存的时候也限制了服务性能。