Java程序在运行过程中,所有的对象实例都存储在堆内存中,而栈内存或方法区中保存的是指向这些对象的引用。理解引用与内存管理,是写出稳定高效Java程序的基础。

一、Java中的四种对象引用类型
Java从JDK1.2开始明确了四种引用类型,它们决定了对象被垃圾回收的时机。
- 强引用:最常见的引用,如 Object obj = new Object(),只要强引用存在,对象不会被回收。
- 软引用:内存不足时才会被回收,适合做缓存。
- 弱引用:下一次垃圾回收时必然被回收。
- 虚引用:唯一作用是在对象被回收时收到系统通知。
示例代码
下面代码演示了弱引用的基本用法:
import java.lang.ref.WeakReference;
public class ReferenceDemo {
public static void main(String[] args) {
// 创建一个强引用对象
Object obj = new Object();
// 使用弱引用包裹该对象
WeakReference<Object> weakRef = new WeakReference<>(obj);
// 去掉强引用
obj = null;
// 主动触发垃圾回收
System.gc();
// 弱引用中的对象可能已被回收
System.out.println(weakRef.get());
}
}
二、内存分配与垃圾回收机制
Java堆通常分为新生代和老年代。新创建的对象优先在新生代分配,经过多次回收仍存活的对象会进入老年代。
可达性分析算法
垃圾回收器通过GC Roots作为起点,向下搜索引用链。如果一个对象到GC Roots没有任何引用链相连,则判定为不可达,可以被回收。
| 区域 | 特点 | 回收频率 |
|---|---|---|
| 新生代 | 对象存活时间短 | 高 |
| 老年代 | 对象存活时间长 | 低 |
三、常见内存问题与控制建议
如果集合中持续保存强引用对象,容易造成内存泄漏。使用WeakHashMap可以在键不再被使用时自动释放对应条目。
使用WeakHashMap避免泄漏
import java.util.WeakHashMap;
public class CacheDemo {
public static void main(String[] args) {
WeakHashMap<String, Object> cache = new WeakHashMap<>();
String key = new String("tmp");
cache.put(key, new Object());
// 移除外部强引用
key = null;
System.gc();
// 对应条目可能被回收
System.out.println(cache.size());
}
}
合理选择引用类型,关注对象生命周期,是掌握Java内存管理的关键。在开发中应尽量避免无意义的长生命周期强引用,必要时借助软引用或弱引用实现缓存与资源释放。