堆内存结构:Jvm调优主要针对堆内存中的对象,调优是对堆内存中的参数进行合理设置
1)堆内存中对象的分配的基本策略
2)堆空间的基本结构:
它用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据
1.新生区
1.1伊甸区(Eden space)
所有的类都是在伊甸区被new出来的
1.2幸存者区(Survivor pace)
1.3老年区(永代区-方法区)
1.4永代区-方法区
永久存储区是一个常驻内存区域,用于存放JDK自身所携带的 Class,Interface 的元数据,也就是说它存储的是运行环境必须的类信息,被装载进此区域的数据是不会被垃圾回收器回收掉的,关闭 JVM 才会释放此区域所占用的内存。
触发Minor GC
当伊甸园的空间用完时,程序又需要创建对象,JVM的垃圾回收器将对伊甸园区进行垃圾回收(Minor GC),将伊甸园区中的不再被其他对象所引用的对象进行销毁。然后将伊甸园中的剩余对象移动到幸存 0区。
触发FullGC
若幸存 0区也满了,再对该区进行垃圾回收,然后移动到 1 区。那如果1 区也满了呢?再移动到养老区。若养老区也满了,那么这个时候将产生MajorGC(FullGC),进行养老区的内存清理。若养老区执行了Full GC之后发现依然无法进行对象的保存,就会产生OOM异常“OutOfMemoryError”。
触发异常
如果出现java.lang.OutOfMemoryError: Java heap space异常,说明Java虚拟机的堆内存不够。原因有二:
(1)Java虚拟机的堆内存设置不够,可以通过参数-Xms、-Xmx来调整。
(2)代码中创建了大量大对象,并且长时间不能被垃圾收集器收集(存在被引用)。
MinorGC的过程(复制->清空->互换)
1:eden、SurvivorFrom 复制到 SurvivorTo,年龄+1
首先,当Eden区满的时候会触发第一次GC,把还活着的对象拷贝到SurvivorFrom区,当Eden区再次触发GC的时候会扫描Eden区和From区域,对这两个区域进行垃圾回收,经过这次回收后还存活的对象,则直接复制到To区域(如果有对象的年龄已经达到了老年的标准,则赋值到老年代区),同时把这些对象的年龄+1
2:清空 eden、SurvivorFrom
然后,清空Eden和SurvivorFrom中的对象,也即复制之后有交换,谁空谁是to
3:SurvivorTo和 SurvivorFrom 互换
最后,SurvivorTo和SurvivorFrom互换,原SurvivorTo成为下一次GC时的SurvivorFrom区。部分对象会在From和To区域中复制来复制去,如此交换15次(由JVM参数MaxTenuringThreshold决定,这个参数默认是15),最终如果还是存活,就存入到老年代
前置:垃圾机制是调优核心原理,垃圾回收算法决定处理效率,必须做到精确控制垃圾回收次数
1)确定垃圾啥时被回收
1.引用计数法(计数器算法)
2可达性分析
虚拟机栈(栈帧中的本地变量表)中引用的对象
方法区中类静态属性引用的对象
方法区中常量引用的对象
本地方法栈中JNI引用的对象
2)GC种类
a.普通GC(minor GC)
新生代:大部分的新创建对象分配在新生代。因为大部分对象很快就会变得不可达,所以它们被分配在新生代,然后消失不再。当对象从新生代移除时,我们称之为"minor GC"。
b.全局GC(major GC or Full GC)
老年代:存活在新生代中但未变为不可达的对象会被复制到老年代。一般来说老年代的内存空间比新生代大,所以在老年代GC发生的频率较新生代低一些。当对象从老年代被移除时,我们称之为"major GC"(或者full GC)。
3)垃圾回收算法
垃圾收集器:垃圾算法具体实现是各种垃圾收集器
1)种类
2)各种垃圾收集器
参数说明
堆的参数配置