图片描述:java
加载过程当中会先检查类是否被已加载,检查顺序是自底向上,从Custom ClassLoader到BootStrap ClassLoader逐层检查,只要某个classloader已加载就视为已加载此类,保证此类只全部ClassLoader加载一次。而加载的顺序是自顶向下,也就是由上层来逐层尝试加载此类。算法
JVM是基于栈的体系结构来执行class字节码的。线程建立后,都会产生程序计数器(PC)和栈(Stack),程序计数器存放下一条要执行的指令在方法内的偏移量,栈中存放一个个栈帧,每一个栈帧对应着每一个方法的每次调用,而栈帧又是有局部变量区和操做数栈两部分组成,局部变量区用于存放方法中的局部变量和参数,操做数栈中用于存放方法执行过程当中产生的中间结果。tomcat
全部经过new建立的对象的内存都在堆中分配,其大小能够经过-Xmx和-Xms来控制。堆被划分为新生代和旧生代,新生代又被进一步划分为Eden和Survivor区,最后Survivor由From Space和To Space组成,结构图以下所示:多线程
每一个线程执行每一个方法的时候都会在栈中申请一个栈帧,每一个栈帧包括局部变量区和操做数栈,用于存放这次方法调用过程当中的临时变量、参数和中间结果并发
用于支持native方法的执行,存储了每一个native方法调用的状态jvm
存放了要加载的类信息、静态变量、final类型的常量、属性和方法信息。JVM用持久代(Permanet Generation)来存放方法区,可经过-XX:PermSize和-XX:MaxPermSize来指定最小值和最大值spa
JVM针对新生代和旧生代采用了不一样的GC线程
新生代一般存活时间较短,所以基于Copying算法来进行回收,所谓Copying算法就是扫描出存活的对象,并复制到一块新的彻底未使用的空间中,对应于新生代,就是在Eden和From Space或To Space之间copy。指针
新生代采用空闲指针的方式来控制GC触发,指针保持最后一个分配的对象在新生代区间的位置,当有新的对象要分配内存时,用于检查空间是否足够,不够就触发GC。server
用java visualVM来查看,能明显观察到新生代满了后,会把对象转移到旧生代,而后清空继续装载,当旧生代也满了后,就会报outofmemory的异常,以下图所示:
在执行机制上JVM提供了串行GC(Serial GC)、并行回收GC(Parallel Scavenge)和并发GC(ParNew)。
旧生代与新生代不一样,对象存活的时间比较长,比较稳定,所以采用标记(Mark)算法来进行回收,所谓标记就是扫描出存活的对象,而后再进行回收未被标记的对象,回收后对用空出的空间要么进行合并,要么标记出来便于下次进行分配,总之就是要减小内存碎片带来的效率损耗。
在执行机制上JVM提供了串行GC(Serial MSC)、并行GC(parallel MSC)和并发GC(CMS)。
你吃饭吃到一半,电话来了,你一直到吃完了之后才去接,这就说明你不支持并发也不支持并行。
你吃饭吃到一半,电话来了,你停了下来接了电话,接完后继续吃饭,这说明你支持并发。
你吃饭吃到一半,电话来了,你一边打电话一边吃饭,这说明你支持并行。
指定方式 | 新生代GC方式 | 旧生代GC方式 |
---|---|---|
-XX:+UseSerialGC | 串行GC | 串行GC |
-XX:+UseParallelGC | 并行回收GC | 并行GC |
-XX:+UseConeMarkSweepGC | 并行GC | 并发GC |
-XX:+UseParNewGC | 并行GC | 串行GC |
-XX:+UseParallelOldGC | 并行回收GC | 并行GC |
-XX:+ UseConeMarkSweepGC -XX:+UseParNewGC | 串行GC | 并发GC |
不支持的组合 | 一、-XX:+UseParNewGC -XX:+UseParallelOldGC 二、-XX:+UseParNewGC -XX:+UseSerialGC |