有关JVM的简要总结
一、JVM作用
1.1、概述:
想要运行一个Java代码,需要具备JRE环境(JDK中已经涵盖了JRE)。在JRE中,包括了Java的虚拟机和核心类库。
由于Java在硬件上运行不现实(因为是高级语言,语法复杂,抽象),所以在运行Java程序之前,需要进行转换。
转换的过程是编译器将Java程序转换成该虚拟机所能识别的指令(序列码,即class文件),加载到JVM中。
过程简要如下
class文件 =>JVM=>操作系统=>底层硬件
Note:JVM是运行在操作系统之上的,与硬件没有直接的交互。
1.2、运行时内存划分
Java虚拟机将运行时内存划分为五个部分。
分别为:
方法区
堆
Pc寄存器
Java方法栈
本地方法栈
下面会特别特别简要的概述。
二、类加载器
2.1、类加载器分类
启动类加载器=>扩展类加载器=>应用程序加载器
2.2、双亲委派机制
每当一个类加载器接受到加载请求时,先会转接上级,层层递上,如果父 类加载器没有加载,然后下成给下类加载器进行加载。
优点:
1.展示出一种层级的关系,避免类的重复加载,
2.安全考虑(防止Java核心API被用户篡改)
三、JVM运行时内存
3.1、本地方法栈
每个操作系统内部,都有许多的本地方法库,在库内有许多调用本地方法的接口。
3.2、Pc寄存器
每个线程都有一个程序计数器,是一个线程私有的指针。
怎么说呢,就是方法压栈时会有一个指针指向下一个方法…
3.3、方法区
所有的定义方法信息都保存在该区域,该区域属于共享空间。
方法区是一个概念,可以理解成类似与接口的一种规范。
jdk1.7之前 由永久代实现
jdk1.8之后 由元空间实现
3.4、栈
数据结构…
Note:两种异常
StackOverflowError —方法的迭代使用,超出栈深度,栈溢出
OutOfMemoryError —虚拟机申请内存不足
3.5、堆
JVM中管理内存最大的部分,虚拟机启动时创建。堆的大小是可以调节的。
所有的对象实例以及数组都要在堆上分配。
Java堆是垃圾收集器的主要区域,所以又被称为GC堆(Garbage Collected Heap)。
堆内存在逻辑上分为三个部分:
新生区
伊甸区
幸存0区(from/to)
幸存1区(to/from)
里面的具体实现…记住复制必定会交换from 和 to ,谁变成空后 指针为to
养老区
最后的幸存者(默认15次之后)
方法区(元空间实现)
四、GC
JVM在进行回收时不是每次三个区域一起回收的而是有各自的负责部分。
新生区GC — Minor GC
在新生区的伊甸区快满时,引发GC
养老区GC — Full GC 针对于养老区之中,偶尔新生区
在养老区快满时,引发GC
五、垃圾回收的三种方式
5.1、清除
清除是把死亡的对象所占据的空间标记为空闲内存,记录在一个空闲列表上。
在需要建新对象时寻找空闲,划分给新对象。
缺点:
1.会造成内存碎片
举个例子:无法连续分配,还有一个就是大小不合适(比如说空闲的为1M 和 2M 。但是我插入的是3M的对象!!!!)。
2.分配效率低。在访问空闲链表时,指针会逐一的访问。
5.2、压缩
挤呗,挤一挤总会有的。将对象挤在一起,后面内存就空闲出来了。解决了碎片化。
缺点:性能开销巨大。
5.3、复制
前面那个from / to 操作…
缺点:使用效率低下…
六、垃圾回收算法
1.标记复制算法 – 新生区GC
2.标记清除算法 – 养老区GC
3.标记压缩算法 – 解决碎片化
4.标记清除压缩算法 --上述的结合 在多次GC后,进行一次Compact操作