JAVA虚拟机(2)
垃圾回收机制
示例代码:
gc的测试类,基础date就是为了输出方便带了时间,重写了finalize方法,在执行垃圾回收的时候调用
public class GCTest extends Date{
@Override
public String toString() {
return "时间" + this.getTime();
}
/**
* 执行GC的时候会执行这个方法
* @throws Throwable
*/
@Override
protected void finalize() throws Throwable {
super.finalize();
System.out.println("对象被回收" + this.getTime());
}
}
这个类里只有一个消耗大量内存的方法
public class OutOfMemory {
/**
* 消耗大量内存
*/
public static void takeMemory(){
String[] array = new String[50000];
for (int i = 0; i<array.length; i++){
for (int j = 'a'; j<='z'; j++){
array[i] += (char)j;
}
}
}
}
public class Main {
public static void main(String[] args) {
//强引用
GCTest gcTest = new GCTest();
//软引用 这引用可能还有用但是占用大量内存的时候会被gc干掉
SoftReference reference = new SoftReference(new GCTest());
//弱引用 只要gc被调用就一定被回收的
WeakReference weakReference = new WeakReference(new GCTest());
//虚引用
ReferenceQueue queue = new ReferenceQueue();
PhantomReference phantomReference = new PhantomReference(new GCTest(),queue);
1 gcTest = null;
2 System.gc();
//消耗大量内存
3 OutOfMemory.takeMemory();
}
}
运行之后有以下几种情况
1.同时注释掉123 gcTest不会被回收
2.注释掉1 gcTest不会被回收(在最后加个System.gc也是不会被回收)
3.注释掉23 gcTest不会被回收(内存够用)
4.注释掉12、13 gcTest不会被回收
5.注释掉2或则3 gcTest会被回收
垃圾回收算法
1.标记清除:分为两个阶段,标记阶段和清除阶段 坏处:这样会造成内存分片,不连续,如果有一个list长度为4但是现在只有3个连续的片,需要重新开辟内存空间,就有毛病了。
2.复制算法:按内存容量将内存划分为等大小的两块。每次只使用其中一块,当这一块内存满后将尚存活的对象复制到另一块上去,把已使用的内存清掉。
3.标记整理算法:标记阶段和标记清楚算法相同,标记后不是清理对象,而是将存活对象移向内存的一端。然后清除端边界外的对象。
垃圾收集器:
垃圾收集算法是垃圾收集器的理论基础,而垃圾收集器就是其具体实现。下面介绍HotSpot虚拟机提供的几种垃圾收集器。
Serial/Serial Old
最古老的收集器,是一个单线程收集器,用它进行垃圾回收时,必须暂停所有用户线程。Serial是针对新生代的收集器,采用Copying算法;而Serial Old是针对老生代的收集器,采用Mark-Compact算法。优点是简单高效,缺点是需要暂停用户线程。
ParNew
Seral/Serial Old的多线程版本,使用多个线程进行垃圾收集。
Parallel Scavenge
新生代的并行收集器,回收期间不需要暂停其他线程,采用Copying算法。该收集器与前两个收集器不同,主要为了达到一个可控的吞吐量。
Parallel Old
Parallel Scavenge的老生代版本,采用Mark-Compact算法和多线程。
CMS
Current Mark Sweep收集器是一种以最小回收时间停顿为目标的并发回收器,因而采用Mark-Sweep算法。
G1
G1(Garbage First)收集器技术的前沿成果,是面向服务端的收集器,能充分利用CPU和多核环境。是一款并行与并发收集器,它能够建立可预测的停顿时间模型。