垃圾回收
垃圾回收(Garbage Collection, GC)是JVM自动管理内存的机制,负责回收不再使用的对象占用的内存空间。Java开发者不需要手动释放内存,这大大减少了内存泄漏和指针错误的风险。
为什么需要垃圾回收
- 防止内存泄漏
 
- 避免手动内存管理的复杂性
 
- 提高开发效率
 
- 保证程序稳定性
 
垃圾回收的基本原理
对象存活判断
引用计数法(Java未采用)
1 2 3 4 5 6 7 8 9 10 11 12 13 14
   | class Object {     int refCount = 0;
      void addReference() {         refCount++;     }
      void removeReference() {         refCount--;         if (refCount == 0) {                      }     } }
  | 
 
可达性分析算法(Java采用)
从GC Roots对象开始,向下搜索引用链,不在引用链上的对象被视为可回收。
GC Roots包括:
- 虚拟机栈中引用的对象
 
- 方法区中类静态属性引用的对象
 
- 方法区中常量引用的对象
 
- 本地方法栈中JNI引用的对象
 
引用类型
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
   | import java.lang.ref.*; public class ReferenceTypes {     public static void main(String[] args) {                  Object strongRef = new Object();
                   SoftReference<Object> softRef = new SoftReference<>(new Object());
                   WeakReference<Object> weakRef = new WeakReference<>(new Object());
                   ReferenceQueue<Object> queue = new ReferenceQueue<>();         PhantomReference<Object> phantomRef = new PhantomReference<>(new Object(), queue);
          System.out.println("Strong: " + strongRef);         System.out.println("Soft: " + softRef.get());         System.out.println("Weak: " + weakRef.get());         System.out.println("Phantom: " + phantomRef.get());
                   System.gc();         System.out.println("After GC:");         System.out.println("Strong: " + strongRef);         System.out.println("Soft: " + softRef.get());         System.out.println("Weak: " + weakRef.get());         System.out.println("Phantom: " + phantomRef.get());     } }
   | 
 
垃圾回收算法
标记-清除算法
缺点:产生内存碎片
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
   | void markAndSweep() {          for (Object obj : heap) {         if (isReachable(obj)) {             obj.marked = true;         }     }
           for (Object obj : heap) {         if (!obj.marked) {             free(obj);         }     } }
  | 
 
复制算法
将内存分为两块,只使用其中一块。GC时将存活对象复制到另一块,然后清除当前块。
优点:无内存碎片
缺点:内存利用率低
1 2 3 4 5 6 7 8 9
   | void copy() {     for (Object obj : fromSpace) {         if (isReachable(obj)) {             copyTo(obj, toSpace);         }     }     swap(fromSpace, toSpace);     clear(toSpace); }
  | 
 
标记-整理算法
优点:无内存碎片,内存利用率高
缺点:移动对象成本高
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
   | void markAndCompact() {          for (Object obj : heap) {         if (isReachable(obj)) {             obj.marked = true;         }     }
           int newAddr = 0;     for (Object obj : heap) {         if (obj.marked) {             move(obj, newAddr);             newAddr += obj.size;         }     }
           freeMemoryFrom(newAddr); }
  | 
 
JVM内存分代与GC类型
堆内存结构
1 2 3 4 5 6
   | Young Generation (1/3 heap) ├─ Eden (80%) ├─ Survivor 0 (10%) └─ Survivor 1 (10%) Old Generation (2/3 heap) PermGen/Metaspace (非堆)
   | 
 
GC类型
- Minor GC/Young GC:只收集年轻代
 
- Major GC/Old GC:只收集老年代
 
- Full GC:收集整个堆(年轻代+老年代+方法区)
 
对象分配与晋升流程
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
   | public class ObjectLifecycle {     public static void main(String[] args) {                  Object obj1 = new Object();  
                   for (int i = 0; i < 100000; i++) {             new Object();           }
                   Object longLivedObj = new Object();         for (int i = 0; i < 15; i++) {             System.gc();           }     } }
  | 
 
垃圾收集器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
   | 串行收集器 -XX:+UseSerialGC
  并行收集器(吞吐量优先) -XX:+UseParallelGC -XX:+UseParallelOldGC
  CMS收集器(低延迟) -XX:+UseConcMarkSweepGC
  G1收集器(平衡型) -XX:+UseG1GC
  ZGC和Shenandoah(超低延迟) -XX:+UseZGC (Java 11+) -XX:+UseShenandoahGC
   | 
 
GC调优示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14
   | public class GCParameters {     public static void main(String[] args) {                           System.out.println("GC Demo");
                   for (int i = 0; i < 100000; i++) {             new Object();         }
          System.gc();       } }
  | 
 
设置GC参数示例
1 2 3 4
   |  java -XX:+UseG1GC -Xms512m -Xmx512m -XX:+PrintGCDetails GCParameters
  java -XX:+UseParallelGC -XX:+UseParallelOldGC -XX:GCTimeRatio=99 -XX:+PrintGCDetails GCParameters
 
  | 
 
常见GC问题与解决方案
内存泄漏
解决方案:及时清除不再需要的引用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
   | import java.util.ArrayList; import java.util.List; public class MemoryLeak {     static List<Object> list = new ArrayList<>();
      public static void main(String[] args) {         while (true) {             list.add(new byte[1024 * 1024]);               try {                 Thread.sleep(100);             } catch (InterruptedException e) {                 e.printStackTrace();             }         }     } }
   | 
 
频繁Full GC问题
可能原因:
- 老年代空间不足
 
- System.gc()调用
 
- 大对象直接进入老年代
 
解决方案:
- 增加堆大小
 
- 调整新生代与老年代比例
 
- 避免手动调用System.gc()
 
现代GC发展趋势
- 低延迟GC:ZGC和Shenandoah的目标是控制在10ms以内的停顿时间
 
- 云原生GC:适应容器环境的内存弹性
 
- AI驱动的GC:根据应用特点自动优化GC参数
 
Java的垃圾回收机制是一个复杂但设计精妙的系统,理解其工作原理对于编写高性能Java应用程序至关重要。不同的应用场景可能需要不同的GC策略和调优方法。建议在实际开发中结合监控工具(如VisualVM、JConsole、GC日志等)来分析应用的内存使用情况,并据此进行调优。