JVM内存分配以及存储总结
最近看了一下JVM的内存分配,还是比较复杂的。这里做个总结,首先一个common sense就是操作系统会为每个java进程实例化一个jvm实例。jvm然后再来运行java程序,具体的过程就不多说了,简单来说就是核心classloader如bootstrap, extention, System对类的加载(一定是此顺序,jvm对类的加载采取的是代理委托方式,防止核心类被hack),找到对应的main入口来运行。
这里主要是想总结一下,每个java进程对应的jvm对内存的分配,运行时是什么样的。我们都知道jvm内存分为 1. PC计数器 2. 堆 3. 栈(jvm栈,本地方法栈) 4. 方法区(包括class信息,静态变量,class文件常量池,运行时常量池,JIT缓存代码)。
其中,PC计数器,栈是线程私有的,而堆和方法区是线程共享的。操作系统分配给jvm的内存的总大小是有限的,这和操作系统以及是32bit还是64bit,具体的jvm实现都有关系。另外,堆和方法区内存的大小是可以在jvm启动参数中配置的。我们程序员平时经常说的内存操作,OOM都是指的堆内存。
这里顺便说一下JVM的GC机制,JVM的GC不是采用的引用计数算法,而是可达性分析算法。堆根据GC回收的分代算法,又可以分为新生代Eden+2*Survivor, 和老年代。对新生代进行标记-复制算法,进行一次Minor GC,而对老年代进行标记-整理算法,进行一次Major/Full GC,当然肯定有一次Minor GC。程序中绝大部分new的对象放置在Eden区,少数比如大型对象,数组,和长期存活对象直接进入老年代。进入新生代的根据对象年龄计数器可以逐步晋升至老年代中。</
