FuLLGC模拟及结果流程

  • Post author:
  • Post category:其他



内存泄漏、内存溢出、CPU飙升三者之间的关系


内存泄露可能会导致内存溢出。 内存溢出会抛出异常,内存泄露不会抛出异常,大多数时候程序看起来是正常运行的。 内存泄露的程序,JVM频繁进行FullGC尝试释放内存空间,进而会导致CPU飙升 内存泄露过多,造成可回收内存不足,程序申请内存失败,结果就是内存溢出。




内存溢出案例分析


一般来说内存溢出主要分为以下几类:

堆溢出(java.lang.OutOfMemoryError: Java heap space) 最常见最复杂情况

栈深度不够( java.lang.StackOverflowError) 需关注配置项 -Xss大小

栈线程数不够(java.lang.OutOfMemoryError: unable to create new native thread)


1、哪些会造成OOM(内存泄漏)?


(1)ThreadLocal的错误使用导致内存泄漏

ThreadLocal可能引起的OOM内存溢出问题简要分析

我们知道ThreadLocal变量是维护在Thread内部的,这样的话只要我们的线程不退出,对象的引用就会一直存在。当线程退出时,Thread类会进行一些清理工作,其中就包含ThreadLocalMap,Thread调用exit方法,但是,当我们使用线程池的时候,就意味着当前线程未必会退出(比如固定大小的线程池,线程总是存在的)。如果这样的话,将一些很大的对象设置到ThreadLocal中(这个很大的对象实际保存在Thread的threadLocals属性中),这样的话就可能会出现内存溢出的情况。


一种场景

就是说如果使用了线程池并且设置了固定的线程,处理一次业务的时候存放到

ThreadLocalMap中一个大对象,处理另一个业务的时候,又一个线程存放到ThreadLocalMap中一个大对象,但是这个线程由于是线程池创建的他会一直存在,不会被销毁,这样的话,以前执行业务的时候存放到ThreadLocalMap中的对象可能不会被再次使用,但是由于线程不会被关闭,因此无法释放Thread 中的ThreadLocalMap对象,造成内存溢出。

也就是说,

ThreadLocal在没有线程池使用的情况下,正常情况下不会存在内存泄露

,但是如果使用了线程池的话,就依赖于线程池的实现,如果

线程池不销毁线程的话,那么就会存在内存泄露


故事线:


OOM   =>   FullGC


ThreadLocal  +  线程池


① 在没有使用线程池时,使用ThreadLocal并没有问题

② 在使用线程池后,发生了内存泄漏,最终排查到发生了fullGC

③ 排查之后,发现不合理点:》不能将大对象全部放到ThreadLocal中

》线程执行结束后一定要执行remove方法


知识点:① 线程池原理   ② ThreadLocal实现原理、存储原理、数据结构   ③ FullGC相关JVM

具体讲解:


① —->线程池原理:

线程池状态转移过程:



② ThreadLocal实现原理、存储原理、数据结构



版权声明:本文为XZB119211原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。