直接内存默认大小到底有多大?
Java源码
在Java源码中有关于直接内存的定义
public class VM {
// 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().
//大意是指:
// 如果在Java启动的时候通过 -XX:MaxDirectMemorySize=<size> 指定了直接内存的大小,
// 这个值就会被重置为命令行中的值,否则则在 Runtime.getRuntime().maxMemory() 获取
private static long directMemory = 64 * 1024 * 1024;
// Save a private copy of the system properties and remove
// the system properties that are not intended for public access.
// This method can only be invoked during system initialization.
// 大意为保留系统属性的私有副本并删除不适合公共访问的属性,只能在系统初始化时调用
// 这个方法的调用会在System类初始化的时候调用,下面会列出System方法中的代码
public static void saveAndRemoveProperties(Properties props) {
if (initLevel() != 0)
throw new IllegalStateException("Wrong init level");
@SuppressWarnings({
"rawtypes", "unchecked"})
Map<String, String> sp =
Map.ofEntries(props.entrySet().toArray(new Map.Entry[0]));
// only main thread is running at this time, so savedProps and
// its content will be correctly published to threads started later
savedProps = sp;
// Set the maximum amount of direct memory. This value is controlled
// by the vm option -XX:MaxDirectMemorySize=<size>.
// The maximum amount of allocatable direct buffer memory (in bytes)
// from the system property sun.nio.MaxDirectMemorySize set by the VM.
// The system property will be removed.
//大意:如果设置了-XX:MaxDirectMemorySize=<size>. 直接内存最大值则是设置的值
//否则从Runtime.getRuntime().maxMemory();获取
String s = (String)props.remove("sun.nio.MaxDirectMemorySize");
if (s != null) {
if (s.equals("-1")) {
// -XX:MaxDirectMemorySize not given, take default
//maxMemory是一个native方法需要从源码中找答案
directMemory = Runtime.getRuntime().maxMemory();
} else {
long l = Long.parseLong(s);
if (l > -1)
directMemory = l;
}
}
}
}
System类 初始化是调用VM中saveAndRemoveProperties方法重置直接内存值
public final class System {
/**
* Initialize the system class. Called after thread initialization.
* 初始化System类,县城初始化之后调用
*/
private static void initializeSystemClass() {
sun.misc.VM.saveAndRemoveProperties(props);
}
}
JVM源码
// Runtime.c
//
JNIEXPORT jlong JNICALL
Java_java_lang_Runtime_maxMemory(JNIEnv *env, jobject this)
{
return JVM_MaxMemory();
}
//jvm.cpp
JVM_ENTRY_NO_ENV(jlong, JVM_MaxMemory(void))
JVMWrapper("JVM_MaxMemory");
size_t n = Universe::heap()->max_capacity();
return convert_size_t_to_jlong(n);
JVM_END
//genCollectedHeap.cpp
//这里是计算的是新生代+老年代的大小
size_t GenCollectedHeap::max_capacity() const {
size_t res = 0;
for (int i = 0; i < _n_gens; i++) {
res += _gens[i]->max_capacity();
}
return res;
}
//defNewGeneration.hpp
//这里计算是新生代大小,新生代大小要减去一个幸存者区域
size_t DefNewGeneration::max_capacity() const {
const size_t reserved_bytes = reserved().byte_size();
return reserved_bytes - compute_survivor_size(reserved_bytes, SpaceAlignment);
}
源码中直接内存默认值=新生代+老年代-一个幸存者区。
