内存泄漏

Java多线程编程-(9)-ThreadLocal造成OOM内存溢出案例演示与原理分析

旧时模样 提交于 2019-11-26 17:12:09
前几篇: Java多线程编程-(1)-线程安全和锁Synchronized概念 Java多线程编程-(2)-可重入锁以及Synchronized的其他基本特性 Java多线程编程-(3)-线程本地ThreadLocal的介绍与使用 Java多线程编程-(4)-线程间通信机制的介绍与使用 Java多线程编程-(5)-使用Lock对象实现同步以及线程间通信 Java多线程编程-(6)-两种常用的线程计数器CountDownLatch和循环屏障CyclicBarrier Java多线程编程-(7)-使用线程池实现线程的复用和一些坑的避免 Java多线程编程-(8)-多图深入分析ThreadLocal原理 案例代码 1、首先看一下代码,模拟了一个线程数为500的线程池,所有线程共享一个ThreadLocal变量,每一个线程执行的时候插入一个大的List集合: import java.util.ArrayList; import java.util.List; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class ThreadLocalOOMDemo { private static final int THREAD_LOOP_SIZE = 500 ;

ThreadLocal为什么会内存泄漏

强颜欢笑 提交于 2019-11-26 16:09:31
1、首先看下ThreadLocal的原理图: 在ThreadLocal的生命周期中,都存在这些引用。 其中,实线代表强引用,虚线代表弱引用; 2、ThreadLocal的实现:每个Thread维护一个ThreadLocalMap映射表,这个映射表的key是ThreadLocal实例本身,value是真正需要存储的Object; 3、也就是说ThreadLocal本身不存储值,它只是作为一个key来让线程从ThreadLocalMap获取value,值得注意的是图中的虚线,表示ThreadLocalMap是使用ThreadLocal的弱引用作为key,其在GC时会被回收; 4、ThreadLocalMap使用ThreadLocal的弱引用作为key,如果一个ThreadLocal没有外部强引用来引用它,那么系统 GC 的时候,这个ThreadLocal势必会被回收,这样一来,ThreadLocalMap中就会出现key为null的Entry,就没有办法访问这些key为null的Entry的value,如果当前线程再迟迟不结束的话,这些key为null的Entry的value就会一直存在一条强引用链:Thread Ref -> Thread -> ThreaLocalMap -> Entry -> value永远无法回收,造成内存泄漏。 5、总的来说就是

开发:内存泄漏&内存溢出

邮差的信 提交于 2019-11-26 14:19:23
一、内存泄漏( memory leak ) 1.内存泄漏定义: 申请的内存空间没有被正确释放,导致后续程序里这块内存被永远占用(不可达/无法访问),而且指向这块内存空间的指针不再存在时,这块内存也就永远不可达了,内存空间就这么一点点被蚕食 2.内存泄漏的后果? 少量的内存泄漏可能不会对程序产生影响,但是随着量的累计,程序的性能会逐渐降低。 更糟的是,泄漏的程序可能会用掉太多内存,以致另一个程序失败,而使用户无从查找问题的真正根源。 3.内存泄漏的种类: (1)堆内存泄漏 (Heap leak)。程序员按需动态申请内存时通过malloc,realloc new从堆中分配得到内存,完成后必须通过调用对应的 free或者delete 删掉。如果没有释放掉,那么这块内存会无法使用,就会产生Heap Leak. (2)系统资源泄露(Resource Leak)。主要指程序使用系统分配的资源比如 Bitmap,handle ,SOCKET等没有使用相应的函数释放掉,导致系统资源的浪费,严重可导致系统效能降低,系统运行不稳定。 4.使用C/C++语言开发的软件在运行时,出现内存泄漏。可以使用以下三种方式,进行检查排除: (1)使用工具软件BoundsChecker,BoundsChecker是一个运行时错误检测工具,它主要定位程序运行时期发生的各种错误。 (2) 调试运行DEBUG版程序

使用 Valgrind 检测 C++ 内存泄漏

梦想的初衷 提交于 2019-11-26 11:04:45
Valgrind 的介绍   Valgrind 可以用来检测程序是否有非法使用内存的问题,例如访问未初始化的内存、访问数组时越界、忘记释放动态内存等问题。在 Linux 可以使用下面的命令安装 Valgrind: 1 2 3 4 5 6 $ wget ftp://sourceware.org/pub/valgrind/valgrind-3.13.0.tar.bz2 $ bzip2 -d valgrind-3.13.0.tar.bz2 $ tar -xf valgrind-3.13.0.tar $ cd valgrind-3.13.0 $ ./configure && make $ sudo make install 检测内存泄漏   Valgrind 可以用来检测程序在哪个位置发生内存泄漏,例如下面的程序: 1 2 3 4 5 6 7 8 # include <stdlib.h> int main () { int * array = malloc( sizeof( int)); return 0; }   编译程序时,需要加上 -g 选项: 1 $ gcc -g -o main_c main.c   使用 Valgrind 检测内存使用情况: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 $

使用HandyJSON导致的内存泄漏问题相关解决方法

陌路散爱 提交于 2019-11-26 07:22:07
使用HandyJSON导致的内存泄漏问题相关解决方法 在移动开发中,与服务器打交道是不可避免的,从服务器拿到的接口数据最终都会被我们解析成模型,现在比较常见的数据传输格式是json格式,对json格式的解析可以使用原生的解析方式,也可以使用第三方的,我们的项目中使用的是阿里开源的一个swift编写的解析框架--HandyJSON。 在使用过程中,使用instruments的Leak Checks工具对内存泄漏进行检测时发现了这个框架导致了不少的内存泄漏,如图1-1: 这张图是在APP进入首页并将数据加载完毕时截取的,可以看到,HandyJSON一共导致了28个内存泄漏,如果把整个APP运行一遍,估计内存泄漏的个数会很多很多。 在HandyJSON的GitHub上找到了原因 点击前往 ,是UnsafeMutableRawPointer没有释放导致的,解决方法如下: 在Leak Checks工具中显示了内存泄漏的了类名(Measuable)与方法名(_getBridgedPropertyList),我们找到HandyJSON中的这个类和方法,在里面进行释放UnsafeMutableRawPointer就好了,在方法中加上图1-2中的红框中的代码即可: 添加完代码之后,我们重新检测内存泄漏的情况,发现如图1-3所示: 同样是进入首页并将数据加载完毕,我们发现

JVM参数调优(一)

时间秒杀一切 提交于 2019-11-26 04:58:20
过了段时间没写日志了,今天有空写下,下面写的是jvm相关的概念及调优,开发的朋友平时可以读读其他的书,比如散文方面,为人处世方面的。 1、-XX:+PrintGC 每次触发GC的时候打印相关日志 -XX:+UseSerialGC 串行回收 -XX:+PrintGCDetails 更详细的GC日志 -Xms 堆初始值 -Xmx 堆最大可用值 -Xmn 新生代堆最大可用值 -XX:SurvivorRatio 用来设置新生代中eden空间和from/to空间的比例. -XX:NewRatio 配置新生代与老年代占比 1:2 含以-XX:SurvivorRatio=eden/from=den/to 总结:在实际工作中,我们可以直接将初始的堆大小与最大堆大小相等, 这样的好处是可以减少程序运行时垃圾回收次数,从而提高效率。 -XX:SurvivorRatio 用来设置新生代中eden空间和from/to空间的比例. 2、虚拟机栈溢出 错误原因: java.lang.StackOverflowError 栈内存溢出 栈溢出 产生于递归调用,循环遍历是不会的,但是循环方法里面产生递归调用, 也会发生栈溢出。 解决办法:设置线程最大调用深度 -Xss5m 设置最大调用深度 3、内存溢出与内存泄漏区别 Java内存泄漏就是没有及时清理内存垃圾,导致系统无法再给你提供内存资源(内存资源耗尽);

如何自动检查内存泄漏和句柄耗尽

☆樱花仙子☆ 提交于 2019-11-26 01:42:18
如何自动检查内存泄漏和句柄耗尽 1. 背景 当程序的子模块数量和规模扩大之后,在开发阶段,系统长时间允许后经常会碰到下面一些bug: 内存泄漏。随着时间允许,系统可用的内存越来越少,最后kernel 出现oom 错误; 文件句柄耗尽。程序可以打开的文件、套接字、管道越来越少,最后出错在用完了最后一个可用句柄的代码附近; 死锁。线程拥有一把锁A,正在申请锁B;但在此时锁B被另外一个线程拥有,且那个线程又在申请锁A。形成一个循环等待、占用且不可释放的状态。 调试这些问题,当然可以从代码流程和逻辑出发,结合ps/gdb/proc/core等命令和信息,一步步挖出root cause。但一般要求对代码、线程关系和相关命令比较熟悉,一般耗时较长。所以,一般大型公司都封装了标准的glibc,做了一个wraaper,然后再wrapper里面加入了对上面调试的支持。还有的可采用专业内存泄漏等检查工具,去做代码检测。那么,对于咱工程师而言,能否能自己设计并实现一个资源检查工具呢? 2. 原理 针对上面的三个例子使用中的资源,我们可以归纳成两类:数量有限的共享资源,比如上面空间有限的内存和数量有限的文件句柄;需要独占的互斥资源,比如上面例子中提到的锁。 下面就分别针对这两种情况,分别展开分析。 2.1 对共享资管的检查 共享资源的特点是:总量有限,通过申请接口获得,使用完了之后通过释放接口归还

内存泄漏和内存溢出

ぃ、小莉子 提交于 2019-11-25 22:39:45
背景:当内存中存储的数据越来越多,而GC又没有可以回收的数据,造成OOM GC机制的两种算法: 引用计数算法:对于每个数据的引用,进行计数,增加引用则加1,溢出引用则减1,GC扫码到该对象并且引用数量为0时就会被回收 如果两个对象,有一个属性互相保存对方的引用,此时将两个对象的引用置为null,但是相互对象内部属性还保留了一个引用 此时两个对象计数引用数量都为1,不能被回收,但其实两个对象都被置为了null,希望被回收,这样就出现了问题 所以引用计数算法回收机制不靠谱 可达性分析算法: 从GC ROOS作为起点,整个可以连通的为存活对象,连通不了的对象为可回收对象 内存泄漏:内存泄漏最终导致的内存溢出,为强引用导致 原因:GC不能回收垃圾数据,造成内存泄漏. 对象的引用: 强引用,软引用,弱引用,虚引用 强引用:Object obj = new Object(); 对于强引用,GC永远都不会回收,即使造成OOM也不会被回收 作为成员变量:作为强引用,置为null,可以被回收 作为局部变量:方法执行完成后,可以被回收 软引用:SoftReference<T> ref = new SoftReference(obj);或SoftReference<T> ref = new SoftReference(obj,referenceQueue); 对于软引用,GC在内存不足的时候