直接内存默认大小到底有多大?

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);
}

源码中直接内存默认值=新生代+老年代-一个幸存者区。

经验分享 程序员 微信小程序 职场和发展