当前位置 博文首页 > chixun5623的专栏:jvm - 垃圾回收
注意 : 本系列文章为学习系列,部分内容会取自相关书籍或者网络资源,在文章中间和末尾处会有标注
它使得java程序员不再时时刻刻的关注内存管理方面的工作.
垃圾回收机制会自动的管理jvm内存空间,将那些已经不会被使用到了的"垃圾对象"清理掉",释放出更多的空间给其他对象使用.
Java中的垃圾回收一般是在Java堆中进行,因为堆中几乎存放了Java中所有的对象实例
在java中,对引用的概念简述如下(引用强度依次减弱) :
强引用?: 这类引用是Java程序中最普遍的,只要强引用还存在,垃圾收集器就永远不会回收掉被引用的对象
软引用?: 用来描述一些非必须的对象,在系统内存不够使用时,这类对象会被垃圾收集器回收,JDK提供了SoftReference类来实现软引用
弱引用?: 用来描述一些非必须的对象,只要发生GC,无论但是内存是否够用,这类对象就会被垃圾收集器回收,JDK提供了WeakReference类来实现弱引用
虚引用?: 与其他几种引用不同,它不影响对象的生命周期,如果这个对象是虚运用,则就跟没有引用一样,在任何时刻都可能会回收,JDK提供了PhantomReference类来实现虚引用
如下为相关示例代码
public class ReferenceDemo {
public static void main(String[] arge) {
//强引用
Object object = new Object();
Object[] objects = new Object[100];
//软引用
SoftReference<String> stringSoftReference = new SoftReference<>(new String("SoftReference"));
System.out.println(stringSoftReference.get());
System.gc();
System.out.println(stringSoftReference.get()); //手动GC,这时内存充足,对象没有被回收
System.out.println();
//弱引用
WeakReference<String> stringWeakReference = new WeakReference<>(new String("WeakReference"));
System.out.println(stringWeakReference.get());
System.gc();
System.out.println(stringWeakReference.get()); //手动gc,这时,返回null,对象已经被回收
System.out.println();
//虚引用
//虚引用主要用来跟踪对象被垃圾回收器回收的活动。
//虚引用与软引用和弱引用的一个区别在于:虚引用必须和引用队列 (ReferenceQueue)联合使用。
//当垃圾回收器准备回收一个对象时,如果发现它还有虚引用,就会在回收对象的内存之前,把这个虚引用加入到与之 关联的引用队列中
ReferenceQueue<String> stringReferenceQueue = new ReferenceQueue<>();
PhantomReference<String> stringPhantomReference = new PhantomReference<>(new String("PhantomReference"), stringReferenceQueue);
System.out.println(stringPhantomReference.get());
}
}
当然,关于这几种引用还有很多知识点,本文只做简单的介绍,后续有机会再单独的文章详细介绍.
每个对象都有一个引用计数器 , 新增一个引用的时候就+1,引用释放的时候就-1,当计数器为0的时候,就表示可以回收
引用计数算法的实现简单,判定效率也很高,在大部分情况下它都是一个不错的选择,当Java语言并没有选择这种算法来进行垃圾回收,主要原因是它很难解决对象之间的相互循环引用问题
public class LoopReferenceDemo {
public static void main(String[] args) {
TestA a = new TestA(); //1
TestB b = new TestB(); //2
a.b = b; //3
b.a = a; //4
a = null; //5
b = null; //6
}
}
class TestA {
public TestB b;
}
class TestB {
public TestA a;
}
虽然a和b都为null,但是a和b存在循环引用,这样a和b就永远不会被回收
如果你在互联网上搜索"引用计数器"这个关键字,通常都会得到以上这一个结论,但是究竟为什么a和b不会被回,收其实还是没有说清楚的,下面简单说明一下 :
第一行?: TestA的引用计数器加1,TestA的引用数量为1
第二行?: TestB的引用计数器加1,TestB的引用数量为1
第三行?: TestB的引用计数器加1,TestB的引用数量为2
第四行?: TestA的引用计数器加1,TestA的引用数量为2
内存分布如下图
第五行?: 将a变量设置为null,不再指向堆中的引用,所以TestA的引用计数器减1,TestA的引用数量为1
第六行?: 将b变量设置为null,不再指向堆中的引用,所以TestB的引用计数器减1,TestB的引用数量为1
内存分布如下图
以上的知识点参考 :?https://www.zhihu.com/question/21539353
cs