jvm原理内容概要
一、运行时数据区
程序计数器
用于记录程序执行到的字节码地址。
java虚拟机栈
java方法执行时,创建一个栈帧,保存局部变量表、操作数栈常量池引用等信息。
当线程请求的栈深度超过最大值,即方法嵌套方法层次太深时,会抛出StackOverflowError。
当栈进行动态扩展没有足够的空间时,会抛出OutofMemoryError。
本地方法栈
其他语言的方法栈
堆
垃圾回收的主要区域。
分为两块:新生代和老年代
-Xms:起始大小
-Xmx:最大大小
方法区
用于存放已经被加载的类信息、常量、静态变量即时编译器编译后的代码。
从JDK1.8开始,移除了永久代,将方法区移入元空间,位于本地内存,不在虚拟机内存。
运行时常量池
方法区的一部分,Class文件中的常量池在类被加载后放入这个区域。
二、垃圾收集
垃圾收集主要针对堆和方法区。
其他几个区域因为随着线程产生和销毁,不需要进行垃圾回收。
什么是垃圾?
1.引用计数
引用计数为0的可以回收。
缺点,循环引用的对象不能回收。
2.可达性分析
以GC Roots为起始点,不可达的对象可以被回收。
何时回收?
4中引用类型:强引用、软引用、弱引用、虚引用。
怎么回收?----垃圾收集算法
标记清除、标记整理、复制、分代收集(新生代:复制算法;老年代:标记清除或者标记整理)
垃圾收集算法会在高响应和高吞吐间做平衡。
串行和并行针对用户线程和GC线程能否同时进行来说。
单线程多线程是针对GC线程使用几个线程来说。
Serial----串行,单线程,client场景下,默认新生代收集器
ParNew----串行,多线程,server场景下,默认新生代收集器
只有以上两者可以和CMS配合使用。
Parallel Scavenge----吞吐量优先收集器,用于新生代
Serial Old----Serial的老年代版本
ParNew Old----ParNew的老年代版本
CMS----标记清除算法,可能会产生浮动垃圾
G1----对新生代和老年代一起回收。引入region,维护一个优先列表,根据允许的收集事件,优先回收价值最大的region
三、分配策略
Minor GC和Full GC
minorGC回收新生代,FullGC回收新生代和老年代
内存分配策略:
对象有限分配在Eden:对象先分配在Eden区,如果空间不够,发起Mnor GC,对象会被放到Survivor区域,年龄+1
大对象直接进入老年代:大对象会直接分配到老年代,配置参数:-XX:PretenureSizeThreshold
长期存活的对象进入老年代:当Survivor区域的年龄增加到一定年龄,对象被移动到老年代。配置参数:-XX:MaxTensuringThreshold
动态对象年龄判定:当Survivor对象中相同年龄的对象大于该空间的一半,大于该年龄的对象会直接进入老年代
空间分配担保:
MinorGC之前,jvm会先检查老年代最大可用连续空间是否大于新生代所有对象?
如果大于,则MinorGC安全。
如果不大于,是否允许担保失败?(HandlePromotionFailure值)
如果允许,并且老年代最大可用连续空间大于历次晋升到老年代对象的平均大小,则进行minorGC
如果不允许,或者空间小于,则进行FullGC
Full GC的触发条件:
System.gc()、老年代空间不足、空间分配担保失败、JDK1.7之前版本永久代空间不足、CMS的浮动垃圾导致老年代空间不足
四、类加载机制
类仅在第一次使用时加载
生命周期:加载、验证、准备、解析、初始化、使用、卸载
类加载器:
启动类加载器、扩展类加载器、应用程序类加载器
只有当父亲加载器加载失败,本层次的加载器才会加载。