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

内存溢出和内存泄漏区别

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

溢出案例

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

案例

java 复制代码
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 进行缓存管理

泄漏案例

java 复制代码
// 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 对象逻辑相等时哈希值一致。

💡 修正代码

java 复制代码
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。

相关推荐
bug菌2 分钟前
零基础也能做出AI应用?Trae是如何打破编程"高墙"的?
后端·ai编程·trae
橘子郡1236 分钟前
观察者模式和发布订阅模式对比,Java示例
java
指针满天飞6 分钟前
Collections.synchronizedList是如何将List变为线程安全的
java·数据结构·list
顾林海7 分钟前
Android MMKV 深度解析:原理、实践与源码剖析
android·面试·源码阅读
Java技术小馆7 分钟前
重构 Controller 的 7 个黄金法则
java·后端·面试
用户40993225021219 分钟前
容器化部署FastAPI应用:如何让你的任务系统代码在云端跳舞?
后端·ai编程·trae
Java水解19 分钟前
MySQL 亿级数据表平滑分表实践:基于时间分片的架构演进
后端·mysql
Neo25526 分钟前
Spring 5.3.x 源码:invokeBeanFactoryPostProcessors()详解
后端
金銀銅鐵28 分钟前
[Java] 以 IntStream 为例,浅析 Stream 的实现
java·后端