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

内存溢出和内存泄漏区别

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

相关推荐
普通网友2 分钟前
KUD#73019
java·php·程序优化
IT_陈寒5 分钟前
Redis 性能翻倍的 5 个隐藏技巧,99% 的开发者都不知道第3点!
前端·人工智能·后端
JaguarJack6 分钟前
PHP 桌面端框架NativePHP for Desktop v2 发布!
后端·php·laravel
番茄Salad7 分钟前
自定义Spring Boot Starter项目并且在其他项目中通过pom引入使用
java·spring boot
程序员三明治19 分钟前
详解Redis锁误删、原子性难题及Redisson加锁底层原理、WatchDog续约机制
java·数据库·redis·分布式锁·redisson·watchdog·看门狗
自由的疯28 分钟前
Java 怎么学习Kubernetes
java·后端·架构
自由的疯29 分钟前
Java kubernetes
java·后端·架构
普通网友1 小时前
IZT#73193
java·php·程序优化
rechol1 小时前
C++ 继承笔记
java·c++·笔记
Han.miracle4 小时前
数据结构——二叉树的从前序与中序遍历序列构造二叉树
java·数据结构·学习·算法·leetcode