Java Vritual Machine
JAVA虚拟机:定义Java程序如何在设备上运行的虚拟机器。
总结内容组成包含:编译过程,类的加载,运行时内存空间,垃圾回收算法,垃圾回收器。
编译过程
将Java文件通过 编译器转为 字节码文件也就是.class,通过JAVA虚拟机上的解释器 将字节码文件 转为机器可以识别机器码。
类的加载
主要过程: 加载--》校验--》准备--》解析--》初始化--》使用--》卸载
加载:在内存空间生成代表这个类的.class对象,用于方法区这个类的各种数据入口。
校验:校验在编译之后生成.class文件的内容是否满足jvm的执行的格式要求。
准备:为各种变量使用时分配内存空间。
解析:是将虚拟机常量的虚拟引用变成直接引用。
初始化:这个阶段是在执行类方法的代码。
类加载器:启动类加载器,扩展类加载器,应用类加载器
类加载过程中采用的双亲委派机制。
双亲委派机制:不管那个加载器加载这个类,最终都是委托给顶层的启动类加载器进行加载,这样保证使用不同的类加载器最终得到的都是同一个Object对象。
运行时内存空间
程序计数器:字节码的行号指示器,代表代码执行过程记录执行到哪了位置。
虚拟机栈:是一个栈帧,用于存储类中的方法,每个方法使用过程就是一个方法入栈和出栈,栈帧用来存储数据和部分过程中的结果。
本地方法栈:类似用虚拟机栈,区别虚拟机栈为执行Java方法服务,本地方法栈为native方法服务。
堆(共享区):主要是用于存储对象和数组。
方法区(共享区):存储jvm加载的类信息,常量,静态变量,即使编译器后的数据等。
JVM在运行的过程中分为新生代和老年代
新生代 1/3 | 老年代2/3 |
eden 8/10 f from 1/10 to 1/10 | |
复制算法 | 标记整理算法 |
eden区:是指Java对象新生地点,当这个区数据较多,就会进行垃圾回收
from区:上一次GC幸存者,作为这一次GC的被扫描者。
to区:保留一次GC过程的幸存者。
新生代进入老年代
1)当对象特别大就会直接放入到老年代。
2)当在新生代的对象逃过多次回收就会进入老年代。
垃圾回收算法
如何确定是垃圾?
通过可达性分析法和引用记数法进行判断。
引用记数法:在JAVA中引用和JAVA对象是有关联的,每一次是使用对象都是通过引用的方式进行的,所以通过引用计数器来判断该对象是否可用。
可达性分析法:就是GC ROOT这个节点开始进行,遍历去寻找是否可达到对象的的一个路径,如果可打则证明该对象还在使用,否则就是垃圾。
算法分类
标记清理算法:主要分为俩个阶段,标记和清理阶段,首先对需要回收对象进行标记,当内存空间满,则进行垃圾回收。
缺点:这个会导致存储空间产生大量的碎片化。
复制算法:主要是将内存一分为二,一个内存空间进行存储然后进行标记回收对象,当这个空间满进行垃圾回收,将第一个空间没有被回收的对象复制到另一个空间。
缺点:虽然没有碎片化,内存效率高,但是内存空间变小,利用率变小。
标记整理算法:这个主要在内存空间将需要回收的对象进行标记,当内存空间满则进行垃圾回收,回收之后则进行数据整理。
垃圾回收器
1.新生代:Serial垃圾回收器,ParNew垃圾回收器,ParallerSavenge垃圾回收器
serial :采用复制算法+单线程;它在使用一条线程进行执行,而且当它执行的时候其他线程都停止,直到它执行完毕。
ParNew 复制算法+多线程;除了使用多线程,其他和serial都一样
ParallerSavenge 复制算法+多线程
2.老年代:CMS垃圾回收器,Serial Old垃圾回收器 ,Parallel Old垃圾回收器
CMS 多线程+标记清除算法
主要分为4个阶段:
初始阶段:这个标记GC ROOT能直接关联的对象,停止其他工作线程
并发阶段: 进行GC ROOT跟踪过程,不需要停止其他工作线程
重新标记:修正并发标记期间,因用户线程继续运行二导致标记生产变得的那一部分对象标记记录,任然需要暂停所以的工作线程。
并发清除:清除GC ROOT不可达对象,不需要停止工作线程。
Serial Old 单线程+标记整理算法
Parallel Old 多线程+标记整理算法
G1收集器它是目前最好的收集器,它主要是将堆内存划分为大小固定的几个独立区域,并且跟踪这些区域的垃圾回收进度,在后台还维护一个优先级列表,根据优先级进行回收垃圾多的区域。
jvm虚拟机优化
内存溢出排斥
1.元空间溢出
1.过程产生反射导致大量的类进行加载。
2.过程通过动态代理产生类加载。
2.栈深度不高
1.调用递归函数无限循环。
2.同一时间大量方法被调用。
3.xss配置太小。
3.堆溢出
1.要么设置堆内存空间大小不合适。
2.大量用户进行访问,瞬间产生大量对象创建。