下面的代码将分配大量的直接内存,但不会导致java.lang.OutOfMemoryError:直接缓冲区内存:
//JVM args: -Xms10m -Xmx10m -XX:MaxDirectMemorySize=10m
public class DirectMemoryOOM {
public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
Field f = Unsafe.class.getDeclaredFields()[0];
f.setAccessible(true);
Unsafe us = (Unsafe) f.get(null);
long size = 1024 * 1024 * 1024;
while (true) {
long p = us.allocateMemory(size);
for (int i = 0; i < size; i++) {
us.putByte(p + i, Byte.MAX_VALUE);
}
}
}
}但是下面的代码将得到java.lang.OutOfMemoryError:直接缓冲区内存。我从Java unsafe memory allocation limit中看到了答案,但是ByteBuffer.allocateDirect是使用Unsafe.allocateMemory()实现的
//JVM args: -Xms10m -Xmx10m -XX:MaxDirectMemorySize=10m
public class DirectMemoryOOM {
public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
int size = 1024 * 1024;
System.out.println(sun.misc.VM.maxDirectMemory());
while (true) {
ByteBuffer.allocateDirect(size);
}
}
}为什么第一个限制会失败呢?
发布于 2015-04-17 14:41:13
正如最初的答案所述:Unsafe.allocateMemory()是os::malloc的包装器,它不关心VM施加的任何内存限制。
ByteBuffer.allocateDirect()将调用此方法,但在此之前,它将调用Bits.reserveMemory() (在我的Java7:DirectByteBuffer.java:123版本中),它检查进程的内存使用情况,并抛出您提到的异常。
发布于 2015-04-17 14:47:06
错误来自Bits.reserveMemory,在调用allocateDirect时,它在unsafe.allocateMemory(size)之前被调用。
reserveMemory方法处理此验证:
synchronized (Bits.class) {
if (totalCapacity + cap > maxMemory)
throw new OutOfMemoryError("Direct buffer memory");
reservedMemory += size;
totalCapacity += cap;
count++;
}如果所需的分配高于从
maxMemory = VM.maxDirectMemory();直接调用allocateMemory将继续本机方法,并且不会验证最大容量(这解释了为什么在第一个代码段中没有得到错误),这是--XX:MaxDirectMemorySize的主要目标,如reserveMemory中的注释所解释的那样
// -XX:MaxDirectMemorySize limits the total capacity rather than the
// actual memory usage, which will differ when buffers are page
// aligned.
if (cap <= maxMemory - totalCapacity) {
reservedMemory += size;
totalCapacity += cap;
count++;
return;
}值得一提的是,您的第一个片段实现不是一个好的实践。Bits.java中的注释指定在分配直接内存时始终调用reserveMemory:
// 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) {https://stackoverflow.com/questions/29702028
复制相似问题