本文主要介绍
1.Java虚拟机内存区域
2.判断对象是否存活算法
3.GC算法
一.Java虚拟机内存区域划分
Java把运行时数据区划分成5个区域,分别是 堆,方法区,虚拟机栈,本地方法栈,程序计数器.
1.堆
Java虚拟机所管理的内存中最大的一块.
被所有线程共享.
在虚拟机启动时创建,用于存放对象实例.
是垃圾收集器管理的主要区域.
如果堆中没有内存完成实例分配,并且堆无法扩展,将抛出OutOfMemoryError.
2.方法区
所有线程共享的内存区域.
存储已被虚拟机加载的类信息,常量,静态变量,即时编译器编译后的代码等数据.
当方法区无法满足内存分配需求时,将抛出OutOfMemoryError.
3.虚拟机栈
线程私有,生命周期与线程一样.
每个方法在执行的时候都会创建一个栈帧.
由于存储局部变量表,操作数栈,动态链接方法出口等信息.
为虚拟机使用的Java方法服务.
如果线程请求的栈深度大于虚拟机所允许的深度,将抛出StackOverflowError,
如果虚拟机动态扩展时无法申请到足够的内存,将抛出OutOfMemoryError.
4.本地方法栈
与虚拟机栈类似,不同的是:它为虚拟机使用的Native方法服务.
5.程序计数器
一块较小的内存区域,可看作是当前线程所执行的字节码的行号指示器.
由于Java虚拟机的多线程是通过线程轮流切换并分配处理器执行时间的方式实现的,
为了线程切换后能恢复到正确的执行位置,每个线程都需要一个独立的程序计数器,
并且各线程互不影响,独立存储.
此内存区域是唯一一个在Java虚拟机规范中没有规定OOM的区域.
二.判断对象是否存活的常见算法
1.引用计数法
给对象添加一个引用计数器,有引用时计数器加1,引用失效时计数器减1.
优点:简单,高效
缺点:很难解决对象之间循环引用的问题
2.可达性分析
当一个对象到GC Roots没有任何引用链相连,则判断对象为可回收对象.
哪些对象可作为GC Roots?
(1)虚拟机栈中引用的对象
(2)方法区中类静态属性引用的对象
(3)方法区中常量引用的对象
(4)本地方法栈中JNI引用的对象
三.GC算法
1.标记-清除算法
先标记出需要被回收的对象,标记完成后统一回收被标记的对象.
问题:效率不高,空间问题会产生大量不连续的内存碎片
2.复制算法
划分内存为大小相等的两块
每次只使用其中的一块,当这一块内存用完时,复制还存活的对象到另一块内存中.
问题:内存缩小一半
3.标记-整理算法
标记需要被回收的对象,让所有存活的对象都向一端移动,然后直接清理掉边界以外的内存.
4.分代收集算法
根据对象存活周期的不同将内存划分为新生代和老年代.
不同的年代采用不同的算法.
新生代中每次都有大量的对象死去使用复制算法,
老年代的对象存活率高使用”标记-清理”或”标记-整理”.