java – `ByteBuffer.allocateDirect`和Xmx
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了java – `ByteBuffer.allocateDirect`和Xmx,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含3339字,纯文字阅读大概需要5分钟。
内容图文
![java – `ByteBuffer.allocateDirect`和Xmx](/upload/InfoBanner/zyjiaocheng/820/ce632d6049674824b33d989b37d989b0.jpg)
根据various sources(虽然在JavaDoc中没有特别提到),ByteBuffer.allocateDirect从主JVM堆中分配内存.我可以确认使用Java Mission Control,看到调用ByteBuffer n = ByteBuffer.allocateDirect(Integer.MAX_VALUE)的程序没有使用大量的Java Heap内存:
但是,当限制JVM堆内存时,此堆外内存分配将停止工作.例如,当我使用-Xmx1g选项运行JVM时,allocateDirect调用会导致以下异常:线程“main”中的异常java.lang.OutOfMemoryError:直接缓冲区内存.我不完全理解这个JVM选项如何与堆外直接内存分配相关,因为 – 根据documentation – -Xmx选项设置Java堆空间大小.如果我使用getUnsafe().allocateMemory(Integer.MAX_VALUE)分配内存;内存分配成功.我的JVM如下:
java version “10” 2018-03-20 Java(TM) SE Runtime Environment 18.3
(build 10+46) Java HotSpot(TM) 64-Bit Server VM 18.3 (build 10+46,
mixed mode)
是否期望Xmx和ByteBuffer.allocateDirect之间存在这种行为?
编辑:在JDK 1.7中似乎存在(不可再现的)bug,具有与上述相同的行为.这是一个错误吗?
解决方法:
我不得不寻找寻找原因的寻宝者,但是你走了!
首先,我查看了ByteBuffer#allocateDirect并找到了以下内容:
public static ByteBuffer allocateDirect(int capacity) {
return new DirectByteBuffer(capacity);
}
然后我导航到DirectByteBuffer的构造函数并找到以下方法调用:
Bits.reserveMemory(size, cap);
看看这种方法,我们看到:
while (true) {
if (tryReserveMemory(size, cap)) {
return;
}
if (sleeps >= MAX_SLEEPS) {
break;
}
try {
if (!jlra.waitForReferenceProcessing()) {
Thread.sleep(sleepTime);
sleepTime <<= 1;
sleeps++;
}
} catch (InterruptedException e) {
interrupted = true;
}
}
// no luck
throw new OutOfMemoryError("Direct buffer memory");
这似乎是你收到此错误的地方,但现在我们需要弄清楚它为什么会引起.为此,我查看了对tryReserveMemory的调用并找到了以下内容:
private static boolean tryReserveMemory(long size, int cap) {
long totalCap;
while (cap <= maxMemory - (totalCap = totalCapacity.get())) {
if (totalCapacity.compareAndSet(totalCap, totalCap + cap)) {
reservedMemory.addAndGet(size);
count.incrementAndGet();
return true;
}
}
return false;
}
我对maxMemory字段感到好奇,并查看它的声明位置:
private static volatile long maxMemory = VM.maxDirectMemory();
现在我必须查看VM.java中的maxDirectMemory:
public static long maxDirectMemory() {
return directMemory;
}
最后,让我们看一下directMemory的声明:
// A user-settable upper limit on the maximum amount of allocatable direct
// buffer memory. This value may be changed during VM initialization if
// "java" is launched with "-XX:MaxDirectMemorySize=<size>".
//
// The initial value of this field is arbitrary; during JRE initialization
// it will be reset to the value specified on the command line, if any,
// otherwise to Runtime.getRuntime().maxMemory().
//
private static long directMemory = 64 * 1024 * 1024;
嘿,看那个!如果不使用“-XX:MaxDirectMemorySize =< size>”手动指定,则默认为Runtime.getRuntime().maxMemory(),这是您设置的堆大小.
看到-Xmx1G小于Integer.MAX_VALUE字节,对tryReserveMemory的调用将永远不会返回true,这会导致sleeps> = MAX_SLEEPS,从而跳出while循环,抛出OutOfMemoryError.
如果我们查看Runtime.getRuntime().maxMemory(),那么如果你没有指定最大堆大小,我们就会知道它为什么有效:
/**
* Returns the maximum amount of memory that the Java virtual machine
* will attempt to use. If there is no inherent limit then the value
* {@link java.lang.Long#MAX_VALUE} will be returned.
*
* @return the maximum amount of memory that the virtual machine will
* attempt to use, measured in bytes
* @since 1.4
*/
public native long maxMemory();
内容总结
以上是互联网集市为您收集整理的java – `ByteBuffer.allocateDirect`和Xmx全部内容,希望文章能够帮你解决java – `ByteBuffer.allocateDirect`和Xmx所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。