JVM总结
类加载机制:
类加载的五个过程:
- 加载:类加载获取二进制字节流,将静态储存结构转换成方法区的运行时数据结构 ,并生成该类的class对象,
- 验证:验证文件格式,字节流等,确保该class的信息符合java虚拟机
- 准备:为类变量分配内存并设置初始化值,这些变量使用的内存都在方法区中进行分配
- 解析:将常量池的符号引用变为直接引用,包括类解析,接口解析。字段解析等。
- 初始化:执行类中定义的Java代码
类加载器用来加载java类到java虚拟机中
Java的引用类型:
强引用:当内存不足的时候,JVM宁可出现OutOfMemoryError错误停止,也需要进行保存,并且不会将此空间回收。在引用期间和栈有联系就无法被回收
软引用:当内存不足的时候,进行对象的回收处理,往往用于高速缓存中;mybatis就是其中
弱引用:不管内存是否紧张,只要有垃圾了就立即回收
幽灵引用:和没有引用是一样的
类加载器和类如何加载:
双0亲委派模型(一个类加载器接收到了类加载请求,先给父类加载,如果父类完不成。子类在去尝试加载)
类加载是通过双亲委派模型加载的,所有的请求都会到启动类加载器中
优点:类加载具备了优先级的层次关系,避免了各种加载造成应用程序变的一片混乱
Jvm由那些部分组成:
类加载器,执行引擎,本地方法调用,内存区
什么是jvm
Jvm 是java的虚拟机,是可以跨计算机结构体系来执行java字节码的
Jvm的内存结构:
堆:储存所实例对象的内存,每个对象头都有个指针去指向方法区的该对象的类元信息,是jvm虚拟机中最大的一块,垃圾回收的主要区域,因此也叫GC堆
虚拟机栈:每调用一个方法就会在栈中开辟一个空间,叫做栈帧,每个栈帧中都有,局部变量表,操作栈数,动态链接,方法出口,每个方法执行完要执行出栈
方法区:储存变量,常量,静态变量,还有对象的类元信息
本地方法栈:存储标有native的本地方法。现在很少用了。主要是为了在调用c/c++
程序计数器:每个线程私有的,每一个线程都有一个独立的程序计数器,他是该线程在执行的行号指示器,通过改变计数器来确定下一条指令,异常处理和线程恢复都是根据它来完成
注:(方法区和堆是线程共有的,其余都是线程私有)
GC垃圾回收
怎么确定垃圾是否回收:有俩种方法
1. 引用计数法
每当创建一个对象就会为该对象生成一个计数器,每次引用计数器加一,引用失败计数器减一,直到计数器减为0,该对象则为垃圾回收的对象,这个方法简单容易,但是该方法避免不了对象的循环问题,会造成内存溢出,所以商用 不用这种方法
2.可达性分析性法:
判断该对象和GCroot之间是否有引用链,如果没有则该对象成为回收对象,GCroot就是比较常用的一些对象,
垃圾回收的算法:
-
标记清除算法:优点:回收效率高,实现原理简单,
缺点:清除后,会产生大量不连续内存碎片 -
复制算法:这种算法是复制后再清理,可以避免产生的不连续碎片问题,但是有缺点,内存利用率高目前只有百分之50的
注:堆分为年轻代,老生代,永久代(新版永久代已经删除)
- 标记-整理算法:
优点:这种算法会自动整理内存,不会产生内存不连续碎片
缺点:因为中途涉及到整理,没有标记清除法效率高
GC收集器
Serial系列收集器:
单线程收集器,手机垃圾过程中必须停掉所有线程,这类收集器停顿时间最长
ParNew收集器:
多线程收集器,停顿时间比serial时间短,回收新生代垃圾,可以和CMS配合使用
CMS收集器:
多线程收集器,用于收集老生代垃圾,回收速度快,停顿时间最短(即使有停顿,停顿时间特别短),因为引入了并发回收垃圾机制
缺点:用的回收算法是标记清除算法,产生大量内存碎片,需要整理
会产生浮动垃圾,就得下一次回收
和所有工作线程一起执行,会抢占cpu,降低工作线程的效率
CMS设计机制分为四个阶段
- 初始标记:有停顿
- 并发标记:没停顿和工作线程一起工作
- 重新标记:有停顿
- 并发清除:没停顿和工作线程一起工作
Paraller系列收集器:
多线程收集器,不考虑停顿的长短,大吞吐量的收集垃圾 列:hadoop
GI收集器:
GI收集器是java最新的收集器,他在jdk1.7开始商用,他结合了cms和paraller的优点停顿时间短和大吞吐量,他把整个堆划分成一个个的小区域块,提高了整个内存的理由率,也降低了fullGC的频率
结束生命周期
执行了system.exit()
程序正常执行结束
程序在执行过程中出现 遇到了异常或者错误终止
操作系统出现了错误导致Jvm进程终止
请解释StackOverflowError和OutOfMemeryError的区别?
答:StackOverflowError栈溢出,一般由于递归过多,调用方法过多导致
OutOfMemeryError堆内存溢出,即OOM,由于堆内存中没有被GC回收的对象过多导致。
出现OOM的原因:
(-).Java虚拟机的堆内存设置不够,可以通过参数-Xms和-Xmx来调优
(二)程序中创建了大量对象,并且长时间不能被被垃圾回收器回收(存在引用)
几种常用的内存调试工具:jmap、jstack、jconsole、jhat
jstack可以看当前栈的情况,jmap查看内存,jhat 进行dump堆的信息
mat(eclipse的也要了解一下)