1.jvm内存区域划分
2.jvm GC
2.1判断对象何时被回收的算法:
- 引用计数法:通过对象的引用计数器来判断对象是否还在被引用,每当该对象被引用时计数器就会加一,每当引用失效的时候,计数器就会减一,当对象的引用计数器的值为零的时候,就说明该对象不再被引用了,就可以被回收了。缺点:如果对象存在循环依赖,那就⽆法确定该对象是否应该被回收
- 可达性分析算法:它从一些GC Roots结点开始向下搜索,当对象到GC Roots没有任何引⽤相连时,说明对象是没有被引用,可以被回收的。GC Roots:一些较活跃的引用,像虚拟机栈栈帧中的局部变量、方法区中类的静态变量、java本地方法栈中的本地方法引用的对象等等
2.2回收对象的算法:
- 标记清除算法:对可回收的对象进行标记,然后清理掉。可能会产生大量内存碎片;
- 标记整理算法:和标记清除算法同样先进行标记,之后让所有存活对象向一端进行移动,再清理掉边界以外的区域,存的对象的内存都需要变动,效率低;
- 复制算法:将内存按容量分为大小相等的两块,每次使用其中一块,当这一块内存用完时把还存活的对象复制到另一块内存上,然后清理这一块内存,这样就可以保证内存空间的连续可用
目前的GC一般采用分代回收的方式:年轻代由于对象收集较为频繁,选择复制算法,老年代选择标记清楚或标记整理算法
2.3GC分代回收过程:
默认情况下新生代的内存空间为整个堆的1/3,老年代为2/3。新生代分为三个区,一个Eden区,两个Survivor区,内存比为8:1:1。新的对象在Eden区中生成,Eden区空间不足的时候,将存活对象复制到一个Survivor区,然后清空Eden区。Eden区再次空间不足的时候,进行minor GC,将Eden区和放有存活对象的Survivor区中的存活对象复制到另一个Survivor区,之后清空原来的Eden区和一个Survivor区,完成一次minor GC。当一个对象被多次复制(默认15次)还存活,则将被放去老年代。
2.4经典垃圾收集器:
年轻代:
serial:单线程、复制算法
parnew:多线程、复制算法
parallel scavenge:多线程、复制算法,比较高效,使程序的吞吐量可控。(吞吐量=代码运行时间/(代码运行时间+垃圾收集时间))
老年代:
serial old:单线程、标记整理算法
parallel old:多线程、标记整理算法,控制老年代的吞吐量,搭配parallel scavenge可以控制系统整体吞吐量
CMS:Concurrent Mark Sweep(并发标记清除),它最⼤的不同点就是并发:在GC线程⼯ 作的时候,⽤户线程不会完全停⽌,⽤户线程在部分场景下与GC线程⼀起并发执⾏,避免出现长时间的STW(Stop The World)现象。CMS垃圾收集主要分为五步:初始标记、并发标记、并发预清理、重新标记以及并发清除。把垃圾收集的过程细分了,在收集的某些阶段可以不停止用户线程,处理请求的同时进行垃圾收集。**缺点:**需要预留足够大的内存空间来支撑用户线程和垃圾收集的并发;基于标记清楚算法会产生内存碎片
G1垃圾收集器:可以设定一个STW期望值,G1根据这个时间尽量满足。堆内存在G1中以逻辑形式划分,堆被分为多个同等大小的region,还有一块存放大对象的Humongous区域
*jdk1.8 默认垃圾收集器Parallel Scavenge(新生代)+Parallel Old(老年代)