Java 内存泄漏(Memory Leak)指的是对象已经不再使用,但由于某些引用关系仍然被 GC Roots 引用,导致无法被垃圾回收,长期占用内存。下面从常见原因 → 预防手段 → 实战建议三个层面说明。
static 集合、单例持有 Activity / Request / ConnectionInputStream / OutputStream / Connection / SessionListener、Observer、Handler、Timerremove()// 不推荐
private static List<Object> cache = new ArrayList<>();
// 推荐
private static Map<Key, Value> cache =
new WeakHashMap<>();
try (InputStream in = new FileInputStream(file)) {
// 自动关闭
} catch (IOException e) {
// handle
}
必须关闭的对象:
ConnectionStatement / ResultSetInputStream / OutputStreamSocketSession// 危险
public static List<User> users = new ArrayList<>();
✅ 改进:
private static ThreadLocal<User> userHolder = new ThreadLocal<>();
try {
userHolder.set(user);
// business logic
} finally {
userHolder.remove(); // 必须
}
⚠️ 线程池场景下尤其重要
@Override
public void onDestroy() {
eventBus.unregister(this);
timer.cancel();
}
常见场景:
Activity❌ 自己写 Map 缓存
✅ 使用:
WeakHashMapLinkedHashMap(LRU)CaffeineGuava CacheRedisCache<String, User> cache = Caffeine.newBuilder()
.maximumSize(1000)
.expireAfterWrite(10, TimeUnit.MINUTES)
.build();
// 危险
class Outer {
class Inner extends Thread {}
}
// 安全
static class Inner extends Thread {}
或使用:
private static class MyHandler extends Handler {
private final WeakReference<Activity> ref;
}
jstatjmapjstackjmap -histo 看对象数量jmap -dump + MAT 分析 GC RootsJava 内存泄漏的本质是:该释放的引用没释放。
✅ 写好“生命周期对称代码”
✅ 资源“谁申请谁释放”
✅ 引用“能弱不强,能局不全”
如果你愿意,可以告诉我:
我可以给你更针对性的建议或代码审查。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。