javascript
- RangeError: Maximum call stack size exceeded
- 函数递归调用过深,导致调用栈不断累积,超过 JavaScript 引擎的栈内存 10 万次限制。
- OutOfMemoryError 或类似提示
- 创建了大量对象且未被垃圾回收(如全局变量存储大量数据)
- 处理超大数据集(如加载远超内存限制的文件)
- 内存泄漏(如未清理的定时器、事件监听器、闭包引用等)
python
MemoryError异常- 程序尝试分配的内存超过了系统或 Python 解释器所能提供的最大内存限制。
- 当内存占用超过操作系统限制时,系统可能会直接终止进程(OOM killer 机制),此时不会有 Python 异常,而是直接退出。
- 线程中存在内存泄漏(如循环引用未被垃圾回收、全局缓存未清理)
- 线程池未限制大小,且每个线程都消耗大量内存
- 递归调用未正确终止(Python 递归深度有限制,过深会先报
RecursionError,但极端情况也可能导致内存问题)
- 与线程相关的间接内存问题 – 线程局部存储(Thread Local)滥用 :为每个线程创建大量线程局部变量且未清理
- 线程资源未释放 :如线程中打开的文件、网络连接未关闭,间接导致内存占用增加
- GIL 相关的内存管理问题 **:虽然 Python 有 GIL(全局解释器锁),但内存分配是线程安全的,过多线程同时申请内存可能导致内存碎片,间接引发内存不足
java
- Java 堆溢出 (Heap OOM):java,lang.OutOfMemoryError:Java heap space
- 原因: 对象过多或大对象无法回收
- 元空间溢出 (Metaspace OOM):java.lang.0utOfMemoryError:Metaspace
- 原因: 类加载过多
- 栈溢出 (StackOverflowError):java.lang.StackOverflowError
- 原因: 递归调用过深
- 直接内存溢出 (Direct Memory OOM):java.lang.OutOfMemoryError:Direct buffer memory
- 原因:NIO 的 DirectByteBuffer 分配过多未释放。
常见场景
- 静态集合泄漏
public class MemoryLeak {private static List<Object> list = new ArrayList<>();
public void add(Object obj) {list.add(obj); // 对象一旦加入,就永远无法被 GC 回收
}
}
- 未正确使用 ThreadLocal
public class ThreadLocalLeak {private static ThreadLocal<Session> sessionTL = new ThreadLocal<>();
public void handleRequest() {
try {sessionTL.set(new Session()); // 为当前线程设置值
sessionTL.setName("业务名称") // 方便后续排查
// ... 处理业务逻辑
// 忘记调用 sessionTL.remove();
// 当使用线程池时,线程不会销毁,这个 Session 对象会一直存在
} finnally {sessionTL.remove(); // 必须清理!}
}
}
- 缓存无过期策略
public class SimpleCache {private Map<String, Object> cache = new HashMap<>();
public void put(String key, Object value) {cache.put(key, value);
}
// 缺少一个 remove 方法或自动过期机制
}
解决方案 :使用弱引用(如 WeakHashMap)或使用专业的缓存库(如 Guava Cache, Caffeine),它们支持基于大小和时间的过期策略。
解决方案
- 确认是否存在内存泄漏
- 使用 JVM 内置工具快速验证
- 定位泄漏对象和引用链
- 获取堆转储: 使用 jmap 命令(生产环境常用)、在启动参数中加入(适合预发环境)、使用 JConsole / JVisualVM(图形化界面)
- 分析堆转储
- Eclipse MAT: 这是最强大、最专业的工具,强烈推荐。官网:https://www.eclipse.org/mat/
- JVisualVM: JDK 自带的工具,功能稍弱但方便。
正文完