线程内存溢出

3次阅读
没有评论

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 自带的工具,功能稍弱但方便。

正文完
 0
评论(没有评论)
验证码