数据区
JAVA虚拟机运行时数据区包括:虚拟机栈区,堆区,方法区,本地方法栈,程序计数器
虚拟机栈区:也就是我们常说的栈区,线程私有,存放基本类型,对象的引用和returnAddress,在编译期间完成分配。
堆区,JAVA堆,也称GC堆,所有线程共享,存放对象的实例和数组,JAVA堆是垃圾收集器管理的主要区域。
方法区:所有线程共享,存储已被虚拟机加载的类信息,常量,静态变量,即时编译器编译后的代码等数据。这个区域的内存回收目标主要是针对常量池的对象的回收和对类型的卸载。
程序计数器:线程私有,每个线程都有自己独立的程序计数器,用来指示下一条指令的地址。
标记算法
(1)引用计数器,每当有一个地方引用它,就加1,当引用失效时,就减1
(2)可达性分析算法,通过一系列的称为GC Roots的对象作为起始点,从这些节点开始向下搜索,所走过的路径称为引用链,不在引用链上的对象判定为可回收的对象。
可以作为GC Roots的有:
(1)虚拟机栈中的引用的对象
(2)方法区中的常量引用的对象
(3)方法区中类静态属性引用的对象
(4)本地方法栈中JNI引用的对象
垃圾收集算法
(1)标记-清除算法:此算法分为两步,先标记,后清除。即先通过标记算法标记出所有需要回收的对象,在标记完后,统一回收所有被标记的对象。
缺点:容易产生大量碎片,导致总空闲容量大于申请容量却无法申请的情况。
(2)标记-整理算法:此算法是标记-清除算法的改良版本,也分为两个步骤,先标记,再整理,标记的过程和标记-清除算法一样,标记完后,将存活的对象全部移动到一端,然后直接清理掉端边界以外的内存。
(3)复制算法:将内存划分为两个大小相等的内存区域,但每次只使用其中一块,等这块内存用完时,将存活的对象全部复制到另外一块上面,然后把刚才使用的那一块内存全部清理掉。
缺点:内存缩小为原来的一半
优点:简单,无碎片,高效(但如果存活对象太多时,效率低下)
(4)分代算法:使用最为广泛,根据对象的存活周期的不同将内存划分为几块,一般把JAVA划分为年轻代和老年代,在年轻代中,每次回收都会有大量的对象死去,只存活少部分对象,因此,复制算法更适合年轻代的垃圾回收,在老年代中,由于每个回收都可能只有少部分对象死去,大部分存活,根据这个特点,垃圾回收算法采用标记-清理或标记-整理算法更加合适。