开发易忽视的问题:内存溢出/泄漏案例

119 阅读2分钟

内存溢出和内存泄漏区别

对比项内存溢出(OOM)内存泄漏(Memory Leak)
定义程序请求的内存超出了 JVM 可用内存不再使用的对象仍然被引用,导致 GC 无法回收
本质申请的内存超限,无法再分配对象的生命周期比预期更长,导致无用对象占用内存
影响直接导致程序崩溃程序运行变慢,可能最终导致 OOM
原因过多对象创建、JVM 配置不足、无限递归等没有释放资源(如静态集合、线程、Socket、数据库连接等)
修复方法优化代码、增加 JVM 堆大小、减少无用对象及时释放资源、使用弱引用(WeakReference)、优化对象管理

溢出案例

现象:不断向 堆(Heap) 中分配内存,导致 java.lang.OutOfMemoryError: Java heap space

案例

import java.util.ArrayList;
import java.util.List;

public class HeapOOM {
    static class OOMObject {}

    public static void main(String[] args) {
        List<OOMObject> list = new ArrayList<>();
        while (true) {
            list.add(new OOMObject()); // 不断向 list 添加对象,导致堆溢出
        }
    }
}

原因

  • 不断创建新对象,导致 堆内存被占满,GC 也无法回收。

解决方案

  • 代码优化,避免对象长时间引用
  • 使用 WeakReference 进行缓存管理

泄漏案例

// Leak example
import java.util.HashMap;
import java.util.Map;

public class HashMapLeakDemo {
    public static class Key {
        String title;

        public Key(String title) {
            this.title = title;
        }
    }

    public static void main(String[] args) {
        Map<Key, Integer> map = new HashMap<>();
        map.put(new Key("1"), 1);
        map.put(new Key("2"), 2);
        map.put(new Key("3"), 2);

        Integer integer = map.get(new Key("2"));
        System.out.println(integer);
    }
}

📌 问题分析

  1. Key 类没有 重写 equals()hashCode() 方法
  2. HashMap 依赖 hashCode() 计算存储位置new Key("2") 生成的是新对象,默认 hashCode() 不是同一个,导致 get(new Key("2")) 返回 null
  3. 解决方案:重写 equals()hashCode() 方法,保证 Key 对象逻辑相等时哈希值一致。

💡 修正代码

public static class Key {
    String title;

    public Key(String title) {
        this.title = title;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) return true;
        if (obj == null || getClass() != obj.getClass()) return false;
        Key key = (Key) obj;
        return title.equals(key.title);
    }

    @Override
    public int hashCode() {
        return title.hashCode();
    }
}

🔹 这样 map.get(new Key("2")) 就能正确返回 2 了! 🚀

即使提供了 equals 方法和 hashCode 方法,也要非常小心,尽量避免使用自定义的对象作为 Key。