Garbage Collection,GC
简单介绍Java内存
虚拟机内存运行时的数据区主要有三块:
- 堆(Heap):存放对象实例和数组。全局共享
- 栈(Stack):也叫虚拟机栈,存放基本数据类型,对象引用。线程私有
- 方法区(Method Area):存放 ”类“被加载后的信息,常量,静态变量。全局共享。在HotSpot中也叫”永生代“,两者不等同
**堆:**最大的最重要的部分,逻辑堆。对应图中Java Heaps区。
**方法区:**永生代,主要由类加载器ClassLoader加载类信息。用于储存类的元数据,常量池,字段,静态变量,方法内的局部变量,已编译好的字节码。线程共享。JDK8后类的静态变量和内部字符串分离到逻辑堆。
栈: 对象的引用,八种基本数据类型。
PC 寄存器: 用来给每个线程分配本机进程编号。
垃圾回收
堆
分为“年轻代”与“老年代”。年轻代分为**“Eden”(伊甸园)区和两个大小对等的Servivor区:from区和to区**。在Java内存模型中堆中有详细介绍。这里主要记录回收算法。
年轻代垃圾回收
Mark—Sweep算法,也就是标记清除算法。标记出活着的实例,清除未标记实例。
-
标记存活实例
寻找根对象,遍历所有和根对象有直接或间接引用关系的实例。
根对象主要包括四类对象:
-
stack栈中引用对象:就是指存储在JVM栈中的对象引用。
-
**static静态变量:**静态方法和变量不产生实例,直接由类引用。Java的类是由类加载器加载(java.lang.ClassLoader),类的数据都不在逻辑堆,而是在永生代(Metaspace方法区),类本身一旦被GC清除。他所有的静态变量也一并释放。
-
mian thread: main方法就是一个thread线程。java里线程也都是继承自基类,所以自身也是一个大实例。
-
JNI引用: JNI是支持其他编程语言的本机码和Java字节码相互调用的程序。
概念补充:
-
mutator:指除了垃圾收集器以外的部分。mutator指责一般是new(分配内存),read(从内存读取),write(内容写入内存)。
collector:垃圾收集器。回收不再使用的内存供mutator使用
-
mutator roots(mutator根对象),mutator根对象一般指的是分配在堆内存之外,可以直接被mutator直接访问到的对象,一般是指静态/全局变量以及Thread-Local变量(在Java中,存储在java.lang.ThreadLocal中的变量和分配在栈上的变量 - 方法内部的临时变量等都属于此类).
-
可达对象的定义,从mutator根对象开始进行遍历,可以被访问到的对象都称为是可达对象。这些对象也是mutator(你的应用程序)正在使用的对象。
-
在标记阶段,mutator先中断整个程序的运行。然后collector从根对象开始遍历,对从mutator根对象可以访问到的对象都打上一个标示,在对象header中,将其记录为可达对象。然后清除阶段,collector对堆内存从头到尾进行线性遍历,若发现某个对象没有标记为可达对象,则将其回收
拷贝到其他代区
回收过程:新对象内存分配到Eden区,当Eden空间不足时触发年轻代上的垃圾回收(Minor Garbage Collection),gc触发后,存活对象拷贝到一个Survior区同时年龄增加,并清除Eden中非可达对象。其他代区相同方法依次类推。
老年代垃圾回收
当minor gc发生时,如果Tenured区没有空间容纳新对象时,触发老年代垃圾回收(Major Garbage Collection)。老年代垃圾回收算法取决于JVM用什么垃圾回收器,有三种:Parallel Scavenge(PS),Concurrent Mark Sweep(CMS)还有最新的Garbage First(G1)垃圾收集器。
Garbage First