1、什么是GC算法
GC算法的概念:
垃圾收集 Garbage Collection 通常被称为“GC”,它诞生于1960年 MIT 的 Lisp 语言,经过半个多世纪,目前已经十分成熟了。
jvm 中,程序计数器、虚拟机栈、本地方法栈都是随线程而生随线程而灭,栈帧随着方法的进入和退出做入栈和出栈操作,实现了自动的内存清理,因此,我们的内存垃圾回收主要集中于 java 堆和方法区中,在程序运行期间,这部分内存的分配和使用都是动态的.
2、 关于GC算法的代码分析
代码
import java.util.ArrayList;
import java.util.List;
public class GCReview {
public static void main(String[] args) {
List<Byte[]> list = new ArrayList<>();
int x = 0;
try {
while (true){
list.add(new Byte[1024*1024]);
x++;
}
}catch (Exception e){
e.printStackTrace();
System.err.println("循环次数:" + (x+1));
}
}
}
输出结果
原因分析:数据堆中的数据太多,JVM的回收机制不能及时的回收数据导致堆中的数据溢出,产生异常。或是有数据将该存储的位置占用
1.2、 内存泄漏
概念:
内存泄漏(Memory Leak)是指程序中已动态分配的堆内存由于某种原因程序未释放或无法释放,造成系统内存的浪费,导致程序运行速度减慢甚至系统崩溃等严重后果。
参考代码:
public class GCTest {
public static void main(String[] args) {
GcObject gcObject = new GcObject();
GcObject gcObject1 = new GcObject();
gcObject.instence = gcObject1;
gcObject1.instence = gcObject;
gcObject=null;
gcObject1=null;
}
static class GcObject{
Object instence = null;
}
}
1.2.1 可达性分析算法:(GC Roots(一组活跃的引用))
GC Roots可以理解为由堆外指向堆内的引用, 一般而言,GC Roots包括(但不限于)以下几种:
Java 方法栈桢中的局部变量;
已加载类的静态变量;
JNI handles;
已启动且未停止的 Java 线程。
注意:将枚举出所有的活的对象并将其他的进行判空回收
1.3、 内存溢出
内存溢出(Out Of Memory,简称OOM)是指应用系统中存在无法回收的内存或使用的内存过多,最终使得程序运行要用到的内存大于能提供的最大内存。
2、引用类型:
2.1、强引用:
只要引用存在,垃圾回收器永远不会回收
Object obj = new Object();
//可直接通过obj取得对应的对象 如obj.equels(new Object());
而这样 obj对象对后面new Object的一个强引用,只有当obj这个引用被释放之后,对象才会被释放掉,这也是我们经常所用到的编码形式。
不能被回收
2.2、软引用
非必须引用,内存溢出之前进行回收,可以通过以下代码实现
Object obj = new Object();
SoftReference sf = new SoftReference(obj);
obj = null;
sf.get();//有时候会返回null
这时候sf是对obj的一个软引用,通过sf.get()方法可以取到这个对象,当然,当这个对象被标记为需要回收的对象时,则返回null;
软引用主要用户实现类似缓存的功能,在内存足够的情况下直接通过软引用取值,无需从繁忙的真实来源查询数据,提升速度;当内存不足时,自动删除这部分缓存数据,从真正的来源查询这些数据。
2.3、弱引用
第二次垃圾回收时回收,可以通过如下代码实现
Object obj = new Object();
WeakReference<Object> wf = new WeakReference<Object>(obj);
obj = null;
wf.get();//有时候会返回null
wf.isEnQueued();//返回是否被垃圾回收器标记为即将回收的垃圾
弱引用是在第二次垃圾回收时回收,短时间内通过弱引用取对应的数据,可以取到,当执行过第二次垃圾回收时,将返回null。
弱引用主要用于监控对象是否已经被垃圾回收器标记为即将回收的垃圾,可以通过弱引用的isEnQueued方法返回对象是否被垃圾回收器标记。
只要垃圾回收就会被回收
2.4、虚引用
垃圾回收时回收,无法通过引用取到对象值,可以通过如下代码实现
Object obj = new Object();
PhantomReference<Object> pf = new PhantomReference<Object>(obj);
obj=null;
pf.get();//永远返回null
pf.isEnQueued();//返回是否从内存中已经删除
虚引用是每次垃圾回收的时候都会被回收,通过虚引用的get方法永远获取到的数据为null,因此也被成为幽灵引用。
虚引用主要用于检测对象是否已经从内存中删除。
程序
回收算法:(效率问题)
介绍:
回收算法就是jvm使用相同的两个模块区域来进行存储或回收数据,在一个区域模块中将所有的活跃的数据转移到另一个区域模块中,然后对本区域的进行回收
缺点:空间的利用率较低。
标记整理算法:(数据碎片化问题)
将所有的数据进行标记,然后对区域内标记的数据进行整理