目录
4,Parallel Scanvenge收集器(标记-复制)
一:什么是GC
GC(GarbageCollection)是垃圾回收机制,在Java中开发人员无法使用指针来自由的管理内存,GC是JVM对内存(实际上就是对象)进行管理的方式。GC使得Java开发人员摆脱了繁琐的内存管理工作,让程序的开发更有效率。
二:GC基本原理
Java的内存管理实际上就是对象的管理,其中包括对象的分配和释放。对于程序员来说,分配对象使用new关键字;释放对象时,只要将对象所有引用赋值为null,让程序不能够再访问到这个对象,我们称该对象为"不可达的"。GC将负责回收所有"不可达"对象的内存空间。
对于GC来说,当程序员创建对象时,GC就开始监控这个对象的地址、大小以及使用情况。通常,GC采用有向图的方式记录和管理堆(heap)中的所有对象。通过这种方式确定哪些对象是"可达的",哪些对象是"不可达的"。当GC确定一些对象为"不可达"时,GC就有责任回收这些内存空间。但是,为了保证GC能够在不同平台实现的问题,Java规范对GC的很多行为都没有进行严格的规定。例如,对于采用什么类型的回收算法、什么时候进行回收等重要问题都没有明确的规定。因此,不同的JVM的实现者往往有不同的实现算法。这也给Java程序员的开发带来行多不确定性。本文研究了几个与GC工作相关的问题,努力减少这种不确定性给Java程序带来的负面影响。
1,垃圾回收有哪些特点:
垃圾回收有一下特点:
- 值回收堆内对象,不回收其他物理资源(eg:数据流连接等)
- 无法精确控制内存回收机会,系统会在合适的时机进行内存回收
- 在回收对象之前会调用对象的finalize()方法回收资源,这个方法可能会让其他变量重新引用对象导致对象复活。
2,在垃圾回收中:对象在内存中的状态
- 可达状态:有一个及以上的变量引用着对象。
- 可恢复状态:已经没有变量引用该对象了,但是还没有被调用finalize()方法。系统在回收前会调用finalize()方法,如果在执行finalize方法的时候,重新让一个变量引用了该对象,那该对象会变成可达状态,反之变成不可达状态。
- 不可达状态:在执行finalize()方法后,对象还是没有被变量引用则该对象变成不可达状态。
3,对象的强引用,软引用,弱引用和虚引用是什么?
- 强引用:就是普通变量对对象的引用,强引用不回被系统回收。如果想中断强引用和某个对象之间的关联,可以显示地将引用赋值为null,这样一来的话,JVM在合适的时间就会回收该对象。比如各种集合的移除方法。
- 软引用:软引用是用来描述一些还有用但并非必需的对象。只使用SoftReference类修饰的对象就是一个软引用对象(软可到达对象),如果一个对象只具有软引用,内存空间足够,垃圾回收器就不会回收它;如果内存空间不足了,就会回收这些对象的内存。只要垃圾回收器没有回收它,该对象就可以被程序使用。
SoftReference< People > aSoftRef=new SoftReference< People >(obj)
常常用于缓存操作,把某个对象标记为软引用时,当内存足够就不会回收,内存不足就会回收,比如网页缓存,图片缓存等。并且软引用都会保证在虚拟机抛出OutOfMemoryError之前已经被清除。
软引用对象可以和一个引用队列(ReferenceQueue)联合使用。当jvm对软引用对象引用的对象回收后,会将此软引用对象放入关联的队列中。
-
弱引用:也是用来描述非必需对象的。只使用WeakReference类修饰的对象就是一个弱引用对象(弱可达对象)。弱引用的对象相比软引用拥有更短暂的生命周期。无论内存是否足够,一旦下次垃圾回收器运行后扫描到弱引用,便会回收。 不过,由于垃圾回收器是一个优先级很低的线程,因此不一定会很快发现那些只具有弱引用的对象。
WeakReference< People > reference=new WeakReference< People >(obj);
如果对象被回收WeakReference的get方法就返回null。引用对象可以和一个引用队列(ReferenceQueue)联合使用。当jvm对弱引用对象引用的对象回收后,会将此弱引用对象放入关联的队列中。
Java中有WeakHashMap类,以及ThreadLocal中的ThreadLocalMap内部节点Entry,他们都是WeakReference的实现,他们的key都与被弱引用对象关联,key被回收之后就代表这一个无效的Entry,Entry也可以被回收了。
引用测试:
public class ReferenceTest {
/**
* 1Mb内存
*/
private static final int _1MB = 1024 * 1024;
public static void main(String[] args) throws InterruptedException {
//测试强引用
// testStrongReference();
//测试软引用
// testSoftReference();
//测试弱引用
// testWeakReference();
//测试虚引用
// testPhantomReference();
}
/**
* 测试强引用
*
* @throws InterruptedException
*/
public static void testStrongReference() throws InterruptedException {
byte[] StrongReference1, StrongReference2, StrongReference3, StrongReference4;
StrongReference1 = new byte[1 * _1MB];
StrongReference2 = new byte[1 * _1MB];
//到这里由于内存不足,所以虚拟机会自动尝试一次自动GC,但是由于是强引用,无法清除对象,造成OutOfMemoryError异常
StrongReference3 = new byte[1 * _1MB];
}
/**
* 测试软引用
*
* @throws InterruptedException
*/
public static void testSoftReference() throws InterruptedException {
ReferenceQueue<byte[]> objectReferenceQueue = new ReferenceQueue<>();
SoftReference softReference1, softReference2, softReference3, softReference4;
softReference1 = new SoftReference(new byte[1 * _1MB], objectReferenceQueue);
softReference2 = new SoftReference(new byte[1 * _1MB], objectReferenceQueue);
//到这里由于内存不足,虚拟机会自动尝试一次自动GC
softReference3 = new SoftReference(new byte[1 * _1MB], objectReferenceQueue);
//执行到这里实际上又GC了一次
softReference4 = new SoftReference(new byte[1 * _1MB], objectReferenceQueue);
System.out.println("第一次GC之后的值");
System.out.println(softReference1.get());
System.out.println(softReference2.get());
System.out.println(softReference3.get());
System.out.println(softReference4.get());
System.out.println("===========>");
System.out.println(objectReferenceQueue.poll());
System.out.println(objectReferenceQueue.poll());
System.out.println(objectReferenceQueue.poll());
System.out.println(objectReferenceQueue.poll());
//到这里,尝试手动使虚拟机GC一次,对于软引用,如果内存足够,GC是并不会回收对象的
System.gc();
Thread.sleep(500);
System.out.println("第二