程私有:
程序计数器
是一块比较小的内存空间,记录当前线程的执行字节码的行号指示器,每条线程都有独立的PCRegister。如果执行java方法,那计数器中的值不为0;如果正在执行的是Native方法,计数器中值为0。PCRegister是JVM规范中唯一一个不会产生OOM(OutOfMemoryError异常,虚拟机动态扩展时无法申请到足够的内存)情况的区域。
虚拟机栈
java方法的信息存储在java虚拟机栈中,java的方法执行对应着一个入栈和出栈的操作。如果方法中有递归且递归没有出口,产生死循环,递归方法不停地入栈,此时栈空间不足,就会产生SOF异常(StackOverflowError异常,线程请求的栈深度大于JVM所允许的深度(-Xss设置栈容量))
本地方法栈
服务native方法
HotspotJVM中本地方法栈与虚拟机栈合二为一
线程共享:
堆:
JVM管理的最大内存区域,存放所有的对象实例与数组,是内存回收的主要区域,Java堆又称GC堆。如果堆中无法存放对象实例也无法再扩展时会抛出OOM异常
方法区:
已加载的类信息、静态变量、常量
运行时常量池:
方法区的一部分,字面量与符号引用
字面量:直接写出来的值
符号引用:
2.GC相关:
如何判断对象是否存活
引用计数法:无法解决循环引用问题,导致无用对象仍然判断存活而无法回收,所以jvm不采用引用计数法判断对象是否已死
可达性分析算法:
以GCRoots为起点,产生一条“引用”链
哪些对象可以作为GC Roots?栈中引用的对象,类中静态变量,常量引用的对象
JDK1.2之后关于引用的扩充:
强引用:程序中普遍存在,类似于new称为强引用。对象被任意一个强引用指向,即使抛出OOM异常,也无法回收被强引用指向的对象
软引用:描述有用但不必须的对象(缓存),SoftReference描述软引用。若对象只被软引用指向,当前内存够用时不用回收,当即将抛出OOM异常时,一次性回收所有仅被软引用引用的对象
弱引用:WeakReference,仅被弱引用指向的对象,当GC开始时,会回收掉仅被弱引用指向的对象
虚引用:PhantomReference,虚引用完全不对对象的生存周期产生任何影响,也无法通过虚引用取得一个对象实例。作用:当虚引用指向的对象被GC时,JVM会发回一个回收通知
-> 对象的自我拯救finialize
若对象所在的类覆写了finalize()
该对象的finalize()未被JVM调用过,JVM会调用此对象的finalize()
该对象的finalize()已被JVM调用过,此对象标记为不再存活,可以进行GC
若对象所在的类没有覆写,此对象直接标记为不再存活,可以进行GC
-> 垃圾回收算法
将堆空间分为新生代与老年代,对象默认在新生代产生,新生代对象"朝生夕死",新生代对象的存活率很低(<=2%)
Java采用分代回收算法,新生代采用复制算法,老年代采用标记-整理算法
-Xms:设置堆的最小值
-Xms:设置堆的最小值
-Xmx:设置堆的最大值
-Xmn:设置新生代内存大小
新生代的复制算法:
一块较大的Eden区,两块较小的Survivor-From,Survivor-To区,
step1,当Eden区第一次快满时,将Eden区所有存活对象复制到from区,然后一次性清理掉Eden区
step2:,将Eden区第二次快满时,将Eden区与from区的存活对象复制到To区,一次性清理到Eden区与From区
… 对象在from和to区中循环复制
若对象在from与to区来回复制15(默认)次以上,将此对象移动到老年代
新生代GC比老年代GC速度快10倍以上,发生频率高的多,为什么老年代不采用复制算法?
因为老年代对象存活率很高,若采用复制算法,复制开销远高于新生代,不适合复制算法
3.JDK内置工具使用
jps:当前JVM进程id
jmap:堆
jstack:栈
4.JMM
volatile
—可见性
—禁止指令重排:1.volatile代码既不会提前也不会滞后 2.volatile代码前的代码一定会全部执行完毕,volatile后的所有代码一定还未开始