前言
搞了这么多年的java,但是对jvm还比较陌生,惭愧…惭愧…
jdk新特性-jvm
jdk9
JDK9新特性-JVM相关3项
1、智能JAVA 编译工具
智能 java 编译工具( sjavac ),用于在多核处理器情况下提升 JDK 的编译速度。其目的是改进 Java 编译工具,并取代目前JDK 编译工具 javac,JDK 9 还更新了 javac 编译器以便能够将 java 9 代码编译运行在低版本 Java 中
2、统一JVM 日志系统
不太知道有什么用,可能是配置和查看jvm日志的时候比较方便吧
3、java 动态编译
不是太清楚
jdk10
1、垃圾回收接口
2、并行Full GC 的G1
3、备用内存设备上分配堆内存
4、基于实验JAVA 的JIT 编译器
上面的都不是太清楚,后面再搞懂吧
class 文件结构
- Class文件详解-魔数:
1) 每一个class文件的头4个字节称为魔数,它唯一的作用是确定这个文件是否为一个能被虚拟机接受的Class文件。
2) 非常多文件存储标准中都使用魔数来进行身份识别。譬如图片格式gif、jpeg等。使用魔数而不是拓展名来进行识别主要是基于安全方面的考虑,由于文件扩展名能够任意修改。
- Minor Version 次版本号 Major Version 主版本号
异常:Unsupported major.minor version 51.0 ,文件的编译版本是JDK1.7,但
是JRE版本小于1.7 - 常量池
红色区域是 CONSTANT_Class_info
蓝色区域是 CONSTANT_Utf8_info
jvm 架构
其中深黄色部分是线程私有,浅黄色部分是线程共有
方法区 method area
概念
- 线程共享
- 用于储存类信息,常量,静态变量
- gc也会对方法区起作用,主要是对常量池的回收,和对类的卸载
- 也会抛出 oom
java虚拟机栈 VM Stack
概念
- 作用于方法执行的一块内存区域
- 每个方法在执行时,都会创建一个栈帧用于储存局部变量表,操作数栈,动态链接,方法出口等信息.一个方法的调用到执行完成对应栈帧被压入虚拟机栈和被弹出虚拟机栈的过程
- 局部变量表存放了编译期可知的各种基本数据类型(boolean、byte、char、short、int、 float、long、double)以及对象引⽤(reference 类型)
- “线程私有”,一个线程分配一个固定的栈大小,超过了就会抛出 StackOverflowError 异常
本地方法栈 Native Method Stack
概念
- 作用于本地方法执行的一块内存区域
- Hotspot将Java虚拟机栈和本地⽅法栈合⼆为⼀
堆 Heap
概念
- 存放对象实例
- 线程共享
- -Xmx -Xms
- 可分为新生代和老年代,新生代可分为To spce ,From space,Eden
程序计数器 Program Counter Register
概念:
- 是一块比较小的内存空间
- 每个线程都有一个独立的程序计数器,“线程私有”
- 行号指示器
对象的创建细节
对象结构
对象存活算法
1. 引⽤计数法
堆中每个对象实例都有⼀个引⽤计数。当⼀个对象被创建时,且将该对象实例分配给⼀个变量,该变量计数设置为1。当任何其它变量被赋值为这个对象的引⽤时,计数加1.但当⼀个对象实例的某个引⽤超过了⽣命周期或者被设置为⼀个新值时,对象实例的引⽤计数器减1。任何引⽤计数器为0的对象实例可以被当作垃圾收集。当⼀个对象实例被垃圾收集时,它引⽤的任何对象实例的引⽤计数器减1
2. 可达性分析
程序把所有的引⽤关系看作⼀张图,从⼀个节点GC ROOT开始,寻找对应的引⽤节点,找到这个节点以后,继续寻找这个节点的引⽤节点,当所有的引⽤节点寻找完毕之后,剩余的节点则被认为是没有被引⽤到的节点,即⽆⽤的节点
3.标记清除
最基础的收集算法是“标记-清除”(Mark-Sweep)算法,如同它的名字⼀样,算法分为“标记”和“清 除”两个阶段
4.复制算法
为了解决效率问题,⼀种称为“复制”(Copying)的收集算法出现了,它将可⽤内存按量划分为⼤⼩相等的两块,每次只使⽤其中的⼀块.
当这⼀块的内存⽤完了,就将还存活着的对象复制到另外⼀块上⾯,然后再把已使⽤过的内
存空间⼀次清理掉。
现在的商业虚拟机都采⽤这种收集算法来回收新⽣代,研究表明,新⽣代中的对象 98%是“朝⽣夕死”的,所以并不需要按照 1:1 的⽐例来划分内存空间,⽽是将内存分为⼀块较⼤的 Eden 空间和两块较⼩的 Survivor 空间,每次使⽤ Eden 和其中⼀块 Survivor。 Survivor from 和Survivor to,内存⽐例 8:1:1
当回收时,将 Eden 和 Survivor 中还存活着的对象⼀次性地复制到另外⼀块 Survivor 空间上,最后清理掉 Eden 和刚才⽤过的 Survivor 空间。HotSpot 虚拟机默认 Eden 和 Survivor 的⼤⼩⽐例是 8:1, 也就是每次新⽣代中可⽤内存空间为整个新⽣代容量的 90% (80%+10%),只有 10% 的内存会被“浪费”。当然,98%的对象可回收只是⼀般场景下的数据,我们没有办法保证每次回收都只有不多于 10%的对象存活,当 Survivor 空间不够⽤时,需要依赖其他内存(这⾥指⽼年代)进⾏分配担保(Handle Promotion)。
5.标记整理算法
复制收集算法在对象存活率较⾼时就要进⾏较多的复制操作,效率将会变低。更关键的是,如果不想浪费 50%的空间,就需要有额外的空间进⾏分配担保,以应对被使⽤的内存中所有对象都 100%存活的极端情况,所以在⽼年代⼀般不能直接选⽤这种算法
根据⽼年代的特点,有⼈提出了另外⼀种“标记-整理(Mark- Compact)算法,标记过程仍然与“标记-清除”算法⼀样,但后续步骤不是直接对可回收对象进⾏清理,⽽是让所有存活的对象都向⼀端移动,然后直接清理掉端边界以外的内存
6分代收集算法
⼀般把 Java 堆分为新⽣代和⽼年代,这样就可以根据各个年代的特点采⽤最适当的收集算法
在新⽣代中,每次垃圾收集时都发现有⼤批对象死去,只有少量存活,那就选⽤复制算法,只需要付出少量存活对象的复制成本就可以完成收集。⽽⽼年代中因为对象存活率⾼、没有额外空间对它进⾏分配担保,就必须使⽤“标记-清理”或者“标记⼀整理”算法来进⾏回收
垃圾收集器
1.Serial
特点: 单线程 ,Stop The World
2.ParNew
特点: Serial 收集器的多线程版本 , 与 CMS 收集器配合⼯作