Java的GC(Garbage Collection)
GC表示垃圾回收
Java基于C++,也叫作C++再–
减去的是垃圾收集部分,让程序员只关注软件中的业务,不用手工释放对象的垃圾。
GC回收哪些数据?堆内存和方法区
什么样的对象你认为是垃圾需要回收?某个对象永远都不需要再使用了,就需要对其进行垃圾回收
垃圾回收,收的是什么?回收对象占用的内存
GC历史
1 串行GC JDK1.3
2 并行GC JDK1.4.2
3 CMS concurrent mark sweep 并发标记清理 JDK1.5
4 G1 JDK7u42 Garbage First 优先垃圾收集,尽可能收集更多的垃圾
Java的引用分类
1强引用 strong reference
Scanner input = new Scanner(System.in);
//此时堆内存的Scanner对象没有任何引用指向,JVM就会回收Scanner类型的对象占用的内存
input =null;
Java 的GC永远都不会回收强引用的对象
2软引用 soft reference
package com.ch.references;
import java.lang.ref.SoftReference;
public class TestSoftReference {
public static void main(String[] args) {
String str = new String("Tom");
//将str由强引用转变为软引用
SoftReference soft = new SoftReference(str);
//JVM运行你的程序,当分配的堆内存有足够的空间,不会回收str占用的内存,如果空间不够了,才会回收软引用str占用的内存
Object value = soft.get();
System.out.println(value);
}
}
3弱引用 weak reference
JVM运行程序,如果一个对象是弱引用状态,不管有没有足够的内存都将回收它(对象)占用的内存
package com.ch.references;
import java.lang.ref.WeakReference;
public class TestWeakReference {
public static void main(String[] args) {
String str = new String("Jerry");
//让str由强引用变为弱引用
WeakReference weak = new WeakReference(str);
//一旦一个对象的引用类型为弱引用,JVM会立马回收
Object value = weak.get();
System.out.println(value);
}
}
4虚引用
不存在的引用
堆内存结构
年轻代
伊甸区 eden
幸存一区 survivor 1 From
幸存二区 survivor 2 To
老年代
GC相关的代码:
package com.ch.gc;
public class TestGC {
public static void main(String[] args) {
System.out.println("Hellowold");
//会回收所有堆内存的对象( 年轻代和老年代) 相当于fullGC
//fullGC 困兽犹斗,FullGC回收垃圾会消耗大量的内存和CPU,让你的程序进入阻塞状态
//工作中不要编写下面的代码
System.gc();
}
/**
*垃圾收集之前会调用该方法,编写对象回收之前的逻辑
*/
protected void finalize() throws Throwable {
System.out.println("AAA");
}
}
JVM垃圾收集相关的参数
-Xmx 最大堆内存大小
-Xms 初始堆内存大小
工作中前两个参数最好保持一致,减少垃圾收集频率,他们的值不要超过计算机内存的1/2
表示最大堆内存和初始堆内存都为8G
-Xmx8192m -Xms8192m
-Xmn 年轻代大小
-Xmn4096m
-Xss 栈内(线程)存大小
-Xss512k
-XX:+printGCDetails 打印垃圾收集的详细信息
package com.ch.gc;
public class TestGC2 {
public static void main(String[] args) {
for(;;) {
//循环一次消耗堆内存1M
byte [] data = new byte[1024*1024];
System.out.println(data);
}
}
}
[GC (Allocation Failure) [PSYoungGen: 294178K->728K(344064K)] 294178K->736K(999424K), 0.0008090 secs][Times: user=0.00 sys=0.00, real=0.00 secs]
-Xmx1024m -Xms1024m -Xmn384m -Xss512k -XX:+PrintGCDetails
1kb=1024byte
1mb=1024kb
1gb=1024mb
-Xmx1024m 表示最大堆内存,默认值 计算机内存的1/8
-Xms1024m 表示初始堆内存,默认值 计算机内存的1/64
工作中前两个参数最好保持一致,减少垃圾收集频率
PSYoungGen:表示年轻代的垃圾收集
294178K->728K(344064K)
344064K 垃圾收集之前年轻代的堆内存空间
294178K 垃圾收集之前年轻代已使用的内存空间
728K 垃圾手机之后年轻代已使用的内存空间
294178K->736K(999424K)
999424K 垃圾收集之前堆内存分配的总空间
294178K 垃圾收集之前堆内存的使用空间
736K 垃圾收集之后堆内存已使用的内存空间
0.0008090 secs 垃圾收集的时间
一旦执行了GC,所有的应用程序逻辑将停止执行
[Full GC (Allocation Failure) [PSYoungGen: 664K->0K(344064K)] [ParOldGen: 524296K->525K(655360K)] 524960K->525K(999424K), [Metaspace: 2654K->2654K(1056768K)], 0.0091301 secs][Times: user=0.00 sys=0.00, real=0.01 secs]
package com.ch.gc;
public class TestGC2 {
public static void main(String[] args) {
for(;;) {
//循环一次消耗堆内存768M
byte [] data = new byte[1024*1024*512];
System.out.println(data);
}
}
}
Full GC 全量垃圾收集
ParOldGen: 524296K->525K(655360K)] 524960K->525K(999424K)
ParOldGen 表示回收老年代对象占用的内存
655360K 表示老年代总的内存空间
524296K 垃圾收集之前 老年代已经使用的内存空间
525K 垃圾收集之后老年代使用的空间
0.0091301 secs FullGC消耗的时间,也表示程序暂停的时间
为某一个运行的程序配置JVM参数
OutOfMemoryError 分配的堆内存空间已经全部耗尽**,还有对象在不断的new,就会出现堆内存溢出错误
Exception in thread “main” java.lang.OutOfMemoryError
并行垃圾回收
-Xmx4096m -Xms4096m -Xmn1536m -XX:+UseParallelGC -XX:+UseParallelOldGC -XX:ParallelGCThreads=2 -XX:+PrintGCDetails
-XX:+UseParallelGC 年轻代使用并行,老年代使用串行
-XX:+UseParallelOldGC 年轻代和老年代都是用并行
XX:ParallelGCThreads=2 使用两个线程做垃圾收集
-XX:+UseConcMarkSweepGC 并发垃圾收集(年轻代使用并行,老年代使用并发收集)
并发垃圾回收
-Xmx4096m -Xms4096m -Xmn1536m -XX:+UseConcMarkSweepGC -XX:+PrintGCDetails