Java一切皆对象
Linux一切皆文件
知识点
- Java内存结构
- 垃圾收集算法
- 垃圾收集器
- 年轻代和老年代的比例和转移流程
- GC Roots
- 四种引用
- 双亲委派机制
- 类加载过程
- 栈溢出和堆溢出
参考书籍
- 《深入理解Java虚拟机》周志明
- 《Offer来了》(原理篇)王磊
- 《Offer来了》(框架篇)王磊
Java虚拟机
- Java虚拟机包括
- 类加载器子系统 (Class Loader SubSystem)
- 执行引擎
- 运行时数据区
- 本地接口库
哪些对象可以作为GC Roots
- 在虚拟机栈中引用对象
- 在方法区中常量引用的对象
- 方法区中静态属性引用的对象
- 在本地方法栈中JNI引用的对象
- Java虚拟机内部的引用
- 所有被同步锁(synchronized关键字)持有的对象
类加载子系统
- 用于将字节码文件(.class文件)加载到JVM中
Java运行时数据区
- 程序计数器
- 虚拟机栈
- 本地方法栈
- 堆
- 方法区
线程私有与共享
- 线程私有:
- 程序计数器
- 虚拟机栈
- 本地方法栈。
- 线程共享
- 堆
- 方法区。
执行引擎
分为两个部分
- 即时编译器:将字节码转换为机器码
- 垃圾回收器
堆的划分
- 新生代:生命周期较短
- 老年代:生命周期较长,大对象
CMS垃圾回收器
-
垃圾回收算法:标记清除
-
优点:并发收集,低停顿。
-
缺点:内存碎片,无法处理浮动垃圾,导致并发失败,最后STW。
concurrent mark sweep 是一种以获取最短停顿时间为目标的收集器 -
Java垃圾回收是由一个守护线程完成的。
-
serial和serial old 串行清除
-
Parallel Scavenge和Parallel Old 并行清除
-
ParNew和CMS 并发清除
CMS四个步骤
- 初始标记:标记与GC Roots直接关联的对象,STW
- 并发标记:GC Roots跟踪标记【并发,耗时较长】
- 重新标记:修正工作线程变动的对象,STW【停顿稍长】
- 并发清除:清除GC Roots不可达对象【并发,耗时较长】
初始标记:标记gc roots直接关联到的对象,速度很快。
并发标记:从gc roots直接关联对象开始遍历整个对象图的过程。
重新标记:修正并发标记期间,因用户程序继续运作而导致标记产生变动的那一部分对象的标记。
并发清除:清理删除掉标记阶段判断的已经死亡的对象。
G1收集器
- 标记整理算法【没有内存碎片】
- 可以指定最大停顿时间
- 划分成region的堆内存布局
- 按收益动态确定回收集
- 在最终标记阶段采用SATB原始快照算法
- H区专门存储大对象
G1运作过程的四个步骤
- 初始标记STW
- 并发标记
- 最终标记STW
- 筛选回收STW
mixed gc
优先处理回收价值收益最大的那些region
G1开创了基于region的堆内存布局,把堆划分为多个大小相等的独立区域region,每个region都可以根据需要,扮演新生代的eden,servivor和老年代空间。
region中有一类特殊的区域H专门用来存储大对象。
超过region容量一半的对象就是大对象。
将region作为单次回收的最小单元
哪块内存中存放的垃圾数量最多,回收收益最大,就回收那一块。
zgc染色指针/内存多重映射/读屏障
类加载器
- 启动类加载器Bootstrap ClassLoader
- 扩展类加载器Extension ClassLoader
- 应用程序类加载器Application ClassLoader
- 自定义加载器
垃圾回收算法
- 标记清除Mark-Sweep
- 标记整理 Mark-Compact
- 复制copying
垃圾回收器
- serial 串行GC
- PS 并行GC jdk1.8默认
- CMS 并行执行垃圾回收同时不阻塞应用程序(STW=200ms)
- G1(STW=10ms) jdk1.9默认
- ZGC(STW=1ms)
双亲委派机制
当某个类加载器需要加载某个.class
文件时,它首先把这个任务委托给他的上级类加载器,递归这个操作,如果上级的类加载器没有加载,自己才会去加载这个类。
类加载器的类别:
- 启动类加载器BootstrapClassLoader(C++编写) rt.jar
- 扩展类加载器ExtClassLoader jre/lib/ext
- 系统类加载器AppClassLoader classpath
- 自定义加载器CustomClassLoader
如果都没加载成功,抛出异常Class Not Found
作用:
-
防止重复加载同一个
.class
。通过委托去向上面问一问,加载过了,就不用再加载一遍。保证数据安全。 -
保证核心
.class
不能被篡改。通过委托方式,不会去篡改核心.clas
,即使篡改也不会去加载,即使加载也不会是同一个.class
对象了。不同的加载器加载同一个.class
也不是同一个Class
对象。这样保证了Class
执行安全。