JVM原理分析
2020-06-19 10:51:14 0 举报
JVM原理及垃圾回收机制分析
作者其他创作
大纲/内容
栈帧
eden:8
并行垃圾回收器也叫做 throughput collector 。它是JVM的默认垃圾回收器。与串行垃圾回收器不同,它使用多线程进行垃圾回收。相似的是,当执行垃圾回收的时候它也会冻结所有的应用程序线程
串行垃圾回收器Serial Garbage Collector
s1
异常情况:1、递归调用,2、常量池无法申请到内存空间,都会报OutOfMemoryError
运算过程,例:局部变量1+局部变量2
包含类的字段、接口、方法等信息,还包含常量池,用来存储编译期间生成的字面量和符号引用
大部分对象在eden区生成,当新对象生成,在Eden区申请空间失败时,会触发一次Scavenge GC,会将能够继续存活的对象复制到survivor区,不能存活的对象回收掉,然后整理survivor区。
heap引用
本地方法栈
动态链接
GC调优
G1垃圾回收器适用于堆内存很大的情况,他将堆内存分割成不同的区域,并且并发的对其进行垃圾回收。G1也可以在回收内存之后对剩余的堆内存空间进行压缩。并发扫描标记垃圾回收器在STW情况下压缩内存。G1垃圾回收会优先选择第一块垃圾最多的区域
虚拟机栈
分代回收:基于对对象生命周期的分析,得出的算法;把对象分为青年代、老年代、持久代,对于处于不同生命周期的对象采用不同的回收策略来进行回收。
直接引用
并行垃圾回收器Parallel Garbage Collector
选择新生代在堆中的比重
JVM运行时数据区(内存)
当一个对象的大小超过了survivor的任何一个区的内存时,就会直接被存放到老年代中(JVM认为占用内存较大的对象一般存活的时间都比较长)
垃圾回收器
3、调整GC类型和内存分配:合理分配内存,采用较快的GC收集器,并找机器优化后对比,选择合理设置。
GC调优应作为最后手段
变量2
运行时常量池
线程共享
新生代1/3
并发标记扫描垃圾回收器CMS Garbage Collector
在JVM中只有一个堆
本地方法栈和虚拟机栈非常相似,区别为:本地方法栈是执行本地方法的,虚拟机栈是执行非本地方法的,执行本地方法时计数器指向的是undefined
发生FullGc的周期足够够长,时间合理,最好是不发生
常量
并行收集:使用多线程处理垃圾回收,效率高、速度快,处理器的个数越多,优势越明显。
5、将最优参数配置全面应用到JVM中
大多数java应用不需要调优
每一个类或接口的常量池运行时的表现形式,在类和接口被加载到JVM中,对应的运行时常量池就被创建出来了;并不是只有class文件常量池中的内容才能进入运行时常量池,在运行时也可以将新的常量放入运行时常量池,例如:String的intern方法;jdk1.7以后将运行时常量池从方法区中移除了,在堆中开辟了一块区域,来存放运行时常量池
其它优化:存储性能优化尽量使用 SSD定时清理数据或者按数据的性质分开存放结果集处理用 setFetchSize 控制 jdbc 每次从数据库中返回多少数据。
串行垃圾回收器通过持有应用程序所有的线程进行工作。它为单线程环境设计,只使用一个单独的线程进行垃圾回收,通过冻结所有应用程序线程进行工作,所以可能不适合服务器环境。它最适合的是简单的命令行程序。
GC时间够小
增量回收:实时回收,即程序一边执行一边回收。
按系统线程分
静态变量
Object对象
GC次数够少
可达性分析
方法区又称为永久代,因为JVM是通过永久代来实现方法区的,从而JVM垃圾收集器能够像管理堆区一样来管理这部分区域,就不需要单独为这部分区域来设计垃圾回收机制。
线程2
survivor
数组
响应时间优先的应用:根据系统的最低响应时间限制,尽可能设大(根据实际情况选择)。在此种情况下,年轻代收集发生的频率也是最小的。同时,减少到达年老代的对象。
按分区对待的方式
选择适合的GC回收器
动态引用,在执行前不知道要引用哪一个,只有在执行的时候才知道引用哪一个
方法区
程序计数器
返回地址
JVM原理图
局部变量表
标记-清除
程序计数器:指向当前线程正在执行的字节码指令的地址(行号),程序计数器所占空间不会随着程序的运行而改变,因此程序计数器不会出现内存溢出,也不存在异常情况
如果满足如下指标一般不需要GC优化:Minor GC执行时间不到50ms;Minor GC执行不频繁,约10s一次;Full GC执行时间不到1s;Full GC执行频率不算频繁,不低于10分钟一次。
大部分需要GC调优的,不是参数调优,而是代码
GC回收模式
操作数栈
句柄池间接引用
先标记,标记完毕后,再清除。效率较低,容易产生内存碎片。
串行收集:使用单线程处理所有的垃圾回收,由于无需多线程交互,因此实现容易,效率较高,缺点:无法发挥多处理器的优势,只适合于单处理器机器、或小数据量的情况下使用。
GC调优最重要的三点
尽可能快速的回收掉那些生命周期短的对象
吞吐量优先的应用:尽可能的设置大,可能到达 GB 的程度。因为对响应时间没有要求,垃圾收集可以并行进行,一般适合 8CPU 以上的应用。避免设置过小.当新生代设置过小时会导致:1、YGC 次数更加频繁 2、可能导致 YGC 对象直接进入老年代,如果此时老年代满了,会触发 FGC。
堆
先标记,标记完毕后,将能够存活的对象整理到内存的一端,不能存活的对象整理到另一端,然后再将不能存活的对象全部清除掉
s0
存放的是在新生代中经历过N次垃圾回收还仍然存活的对象,或者是一些占用内存较大大的对象
。。。
2、分析结果、判断是否需要优化:如果各项参数设置合理,没有超时日志出现,GC的频率不高,GC的耗时不高,那么久没有GC优化的必要;如果GC的时间过长或者频率过高,则必须优化。
JVM参数配置:java -Xmx12m -Xms3m -Xmn1m -XX:PermSize=20m -XX:MaxPermSize=20m -XX:+UseSerialGC -jar java-application.jar
并发收集:每发生一次垃圾收集,它会停掉所有应用的线程并用多个线程执行垃圾回收工作。因此垃圾回收工作可以不受任何中断非常高效地完成。对相关的应用来说,这通常也是最小化垃圾收集工作开销时间的最好方式。然而在个别情况下,因垃圾回收而导致的应用中断也可能会非常长。
1、监控GC状态:使用各种JVM工具,查看当前日志,分析JVM参数设置,分析当前堆内存快照、GC日志,根据实际的各区域内存划分和 GC 执行时间,觉得是否需要进行优化。
虚拟机栈:存储当前线程运行时所需的数据、指令、返回地址
永久代(1.8后改为元空间)
复制算法
方法执行完后要返回的地方
JMM(JVM的内存模型)jdk<1.8
按照回收策略
GC调优的目的
步骤:
线程1
4、不断的分析调整找出最优参数设置。
调优的原则
年轻代大小选择
G1垃圾回收器G1 Garbage Collector
对象有一次引用计数就加1,删除一个引用则减1,当对象引用为0是则回收,缺点:无法处理循环引用。
JVM日志路径配置:-XX:+PrintGCTimeStamps -XX:+PrintGCDetails -Xloggc:d:/GClogs/tomcat6-gc.log
老年代2/3
并发标记垃圾回收使用多线程扫描堆内存,标记需要清理的实例并且清理被标记过的实例。并发标记垃圾回收器只会在下面两种情况持有应用程序所有线程。 当标记的引用对象在tenured区域; 在进行垃圾回收的时候,堆内存的数据被并发的改变。相比并行垃圾回收器,并发标记扫描垃圾回收器使用更多的CPU来确保程序的吞吐量。如果我们可以为了更好的程序性能分配更多的CPU,那么并发标记上扫描垃圾回收器是更好的选择相比并发垃圾回收器。
当survivor中的一个区满了之后会将能够继续存活的对象复制到另一个区,如此循环,当其中存活的对象的年龄达到一定的值(默认值为15)的时候,JVM就会认为这个对象是能够长期存活的,这个时候就会将这个对象存放到老年代。
.class文件编译后的信息
变量1
年老代大小选择
线程私有
对象可达则不回收,不可达则回收。
标记-整理
0:this
局部变量表的大小在编译器就能确定,因此在程序执行期间是不会改变的
选择适合的堆大小
实际情况中,分析GC情况优化代码比优化GC参数要多的多
引用计数
0 条评论
下一页