文章目录
jvm学习笔记
写在最前面
- 本篇为本人自学学习笔记, 优点是简短, 缺点是未必准确.
- 网上的各种学习笔记泥沙俱下, 抠得越深, 越发现对于同一个细节, 存在多种版本的解释.
JVM的架构(HotSpot JDK1.8)
-
类加载器
类加载器的种类:
- 启动类加载器
- 扩展类加载器
- 应用程序加载器
- 自定义加载器
-
运行时数据区
- 线程共享
- 堆
- 新生代
- Eden
- survivor 0
- survivor 1
- 老年代
- 字符串常量池
- 新生代
- 堆
- 线程私有
- 程序计数器
- Java栈
- 局部变量表
- 操作数栈
- 动态链接
- 方法返回地址
- 本地方法栈
- 线程共享
-
执行引擎
-
本地库接口
-
元空间(方法区是规范, 方法区在JDK1.8以前的实现是永久代, 在JDK1.8以后的实现是元空间. 方法区位于本地内存, 而不是虚拟机内存. 存储类的元信息和运行时常量池. )
new一个对象的过程
- 在方法区搜索这个类是否已经被加载
- 如果没有被加载, 使用双亲委派机制查找类加载器
- 使用类加载器, 将类加载到方法区, 生成类的运行时数据结构
- 在堆里面开辟空间存放对象并调用构造函数进行初始化, 这个对象持有指向方法区的引用
- 将栈里面的变量名指向堆里面的对象
类加载器的过程
-
加载
-
链接
- 验证(保证被校验类的方法在运行时不会做出危害虚拟机的事情)
- 准备(为static变量在方法区中分配内存空间)
- 解析(符号引用替换为直接引用)
-
初始化
-
卸载(GC)
对象的年龄变化过程
-
Eden满了以后, Minor GC, 存活对象保存到survivor的from区, 对象年龄变为1
-
survivor的from区满了以后, Minor GC
-
Minor GC以后, 如果对象年龄到达15岁(15岁可以通过-XX:MaxTenuringThreshold改变, 最大15.), 晋升到老年区. 或者按年龄从小到大的顺序累加对象所占空间, 如果所占空间超过了survivor区的50%(50%是默认值, 可以通过参数-XX:TargetSurvivorRatio改变.), 将超过的对象晋升到老年区.
比如1岁的10%, 2岁的20%, 3岁的30%, 10%+20%+30% >= 50%, 那么将3岁及更大的对象拷贝到老年区.
-
老年区满了以后, Full GC(停止所有线程, Stop The World)
GC时如何判断一个对象是否回收
-
引用计数器计算
缺点: 不能回收循环引用的对象
-
可达性分析计算
从GC Roots开始向下搜索, 被引用到的对象都不会被回收.
GC Roots的组成:
- 栈帧中本地变量表引用的对象
- 方法区中类变量和常量引用的对象
- 本地方法栈中JNI引用的对象
- 已开启未停止的线程
扩展: 三色标记算法, 两次标记
垃圾回收算法及收集器
-
分带算法
-
年轻代用复制算法(JDK1.8默认用Parallel Scavenge收集器, 并行.)
-
老年代用标记-整理算法(JDK1.8默认用Parallel Old收集器, 并行.)
-
还有标记-清除算法
备注:
- JDK1.9后默认采用G1收集器, 并发.
-
默认比例
新生代 : 老年代 = 3 : 5
Eden : Survivor0 : Survivor1 = 8 : 1 : 1
-Xms: 默认物理内存的1/64
-Xmx: 默认物理内存的1/4
常用JVM参数
-Xms1024m
-Xmx4096m
-Xmn256m
-XX:NewSize=256m
-XX:MaxNewSize=1024m
-XX:NewRatio=4
-XX:SurvivorRatio=8
-XX:MetaspaceSize=100m
-XX:MaxMetaspaceSize=100m
-XX:+UseParallelGC
-XX:+UseG1GC
-XX:+PrintGCDetails
-XX:+HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath