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

内存溢出和内存泄漏区别

对比项 内存溢出(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。

相关推荐
爱学习的茄子7 分钟前
深入理解JavaScript闭包:从入门到精通的实战指南
前端·javascript·面试
前端付豪14 分钟前
17、自动化才是正义:用 Python 接管你的日常琐事
后端·python
我是一只代码狗18 分钟前
springboot中使用线程池
java·spring boot·后端
hello早上好31 分钟前
JDK 代理原理
java·spring boot·spring
PanZonghui34 分钟前
Centos项目部署之安装数据库MySQL8
linux·后端·mysql
PanZonghui36 分钟前
Centos项目部署之Java安装与配置
java·linux
Victor35637 分钟前
MySQL(119)如何加密存储敏感数据?
后端
用户3966144687191 小时前
TypeScript 系统入门到项目实战-慕课网
后端
guojl1 小时前
Dubbo SPI原理与设计精要
后端