Java JVM 内存泄漏--全解析和处理办法 [ 转载 ]

时间:2023-01-07 19:10:39

Java JVM 内存泄露——全解析和处理办法 [转载]

 
@author 小筐子
@address http://www.jianshu.com/p/bf159a9c391a
 
 
 
 

JAVA是垃圾回收语言的一种,开发者无需特意管理内存分配。但是JAVA中还是存在着许多内存泄露的可能性,如果不好好处理内存泄露,会导致APP内存单元无法释放被浪费掉,最终导致内存全部占据堆栈(heap)挤爆进而程序崩溃

内存泄露

说到内存泄露,就不得不提到内存溢出,这两个比较容易混淆的概念,我们来分析一下。

  • 内存泄露程序在向系统申请分配内存空间后(new),在使用完毕后未释放。结果导致一直占据该内存单元,我们和程序都无法再使用该内存单元,直到程序结束,这是内存泄露。

  • 内存溢出程序向系统申请的内存空间超出了系统能给的。比如内存只能分配一个int类型,我却要塞给他一个long类型,系统就出现oom。又比如一车最多能坐5个人,你却非要塞下10个,车就挤爆了。

大量的内存泄露会导致内存溢出(oom)。

内存

想要了解内存泄露,对内存的了解必不可少。
JAVA是在JVM所虚拟出的内存环境中运行的,JVM的内存可分为三个区:堆(heap)、栈(stack)和方法区(method)。

  • 栈(stack):是简单的数据结构,但在计算机中使用广泛。栈最显著的特征是:LIFO(Last In, First Out, 后进先出)。比如我们往箱子里面放衣服,先放入的在最下方,只有拿出后来放入的才能拿到下方的衣服。栈中只存放基本类型和对象的引用(不是对象)。

  • 堆(heap)堆内存用于存放由new创建的对象和数组。在堆中分配的内存,由java虚拟机自动垃圾回收器来管理。JVM只有一个堆区(heap)被所有线程共享,堆中不存放基本类型和对象引用,只存放对象本身。

  • 方法区(method):又叫静态区,跟堆一样,被所有的线程共享。方法区包含所有的class和static变量。

内存的概念大概理解清楚后,要考虑的问题来了:
到底是哪里的内存会让我们造成内存泄露?

 
 

内存泄露原因分析

在JAVA中JVM的栈记录了方法的调用,每个线程拥有一个栈。在线程的运行过程当中,执行到一个新的方法调用,就在栈中增加一个内存单元,即帧(frame)。在frame中,保存有该方法调用的参数、局部变量和返回地址。然而JAVA中的局部变量只能是基本类型变量(int),或者对象的引用。所以在栈中只存放基本类型变量和对象的引用。引用的对象保存在堆中。

当某方法运行结束时,该方法对应的frame将会从栈中删除,frame中所有局部变量和参数所占有的空间也随之释放。线程回到原方法继续执行,当所有的栈都清空的时候,程序也就随之运行结束。

而对于堆内存,堆存放着普通变量。在JAVA中堆内存不会随着方法的结束而清空,所以在方法中定义了局部变量,在方法结束后变量依然存活在堆中。

综上所述,栈(stack)可以自行清除不用的内存空间。但是如果我们不停的创建新对象,堆(heap)的内存空间就会被消耗尽。所以JAVA引入了垃圾回收(garbage collection,简称GC)去处理堆内存的回收,但如果对象一直被引用无法被回收,造成内存的浪费,无法再被使用。所以对象无法被GC回收就是造成内存泄露的原因!

垃圾回收机制

垃圾回收(garbage collection,简称GC)可以自动清空堆中不再使用的对象。在JAVA中对象是通过引用使用的。如果再没有引用指向该对象,那么该对象就无从处理或调用该对象,这样的对象称为不可到达(unreachable)。垃圾回收用于释放不可到达的对象所占据的内存。

实现思想:我们将栈定义为root,遍历栈中所有的对象的引用,再遍历一遍堆中的对象。因为栈中的对象的引用执行完毕就删除,所以我们就可以通过栈中的对象的引用,查找到堆中没有被指向的对象,这些对象即为不可到达对象,对其进行垃圾回收。

Java JVM 内存泄漏--全解析和处理办法  [ 转载 ]
垃圾回收实现思想

如果持有对象的强引用,垃圾回收器是无法在内存中回收这个对象。

引用类型

在JDK 1.2以前的版本中,若一个对象不被任何变量引用,那么程序就无法再使用这个对象。也就是说,只有对象处于可触及(reachable)状态,程序才能使用它。从JDK 1.2版本开始,把对象的引用分为4种级别,从而使程序能更加灵活地控制对象的生命周期。这4种级别由高到低依次为:强引用、软引用、弱引用和虚引用。
Java/Android引用类型及其使用分析

1. 强引用(Strong reference)
实际编码中最常见的一种引用类型。常见形式如:A a = new A();等。强引用本身存储在栈内存中,其存储指向对内存中对象的地址。一般情况下,当对内存中的对象不再有任何强引用指向它时,垃圾回收机器开始考虑可能要对此内存进行的垃圾回收。如当进行编码:a = null,此时,刚刚在堆中分配地址并新建的a对象没有其他的任何引用,当系统进行垃圾回收时,堆内存将被垃圾回收。

2. 软引用(Soft Reference)
软引用的一般使用形式如下:

A a = new A();
SoftReference<A> srA = new SoftReference<A>(a);

软引用所指示的对象进行垃圾回收需要满足如下两个条件:
1.当其指示的对象没有任何强引用对象指向它;
2.当虚拟机内存不足时。
因此,SoftReference变相的延长了其指示对象占据堆内存的时间,直到虚拟机内存不足时垃圾回收器才回收此堆内存空间。

3. 弱引用(Weak Reference)
同样的,软引用的一般使用形式如下:

A a = new A();
WeakReference<A> wrA = new WeakReference<A>(a);

WeakReference不改变原有强引用对象的垃圾回收时机,一旦其指示对象没有任何强引用对象时,此对象即进入正常的垃圾回收流程。

4. 虚引用(Phantom Reference)
与SoftReference或WeakReference相比,PhantomReference主要差别体现在如下几点:
1.PhantomReference只有一个构造函数

PhantomReference(T referent, ReferenceQueue<? super T> q)

2.不管有无强引用指向PhantomReference的指示对象,PhantomReference的get()方法返回结果都是null。

因此,PhantomReference使用必须结合ReferenceQueue;
与WeakReference相同,PhantomReference并不会改变其指示对象的垃圾回收时机。

内存泄露原因

如果持有对象的强引用,垃圾回收器是无法在内存中回收这个对象。

内存泄露的真因是:持有对象的强引用,且没有及时释放,进而造成内存单元一直被占用,浪费空间,甚至可能造成内存溢出!

其实在Android中会造成内存泄露的情景无外乎两种:
  • 全局进程(process-global)的static变量。这个无视应用的状态,持有Activity的强引用的怪物。
  • 活在Activity生命周期之外的线程。没有清空对Activity的强引用。

检查一下你的项目中是否有以下几种情况:

  • Static Activities
  • Static Views
  • Inner Classes
  • Anonymous Classes
  • Handler
  • Threads
  • TimerTask
  • Sensor Manager

详解见该文章《Android内存泄漏的八种可能》

最后推荐一个可检测app内存泄露的项目:LeakCanary(可以检测app的内存泄露)

 

Java JVM 内存泄漏--全解析和处理办法 [ 转载 ]的更多相关文章

  1. 【知识必备】内存泄漏全解析,从此拒绝ANR,让OOM远离你的身边,跟内存泄漏say byebye

    一.写在前面 对于C++来说,内存泄漏就是new出来的对象没有delete,俗称野指针:而对于java来说,就是new出来的Object放在Heap上无法被GC回收:而这里就把我之前的一篇内存泄漏的总 ...

  2. Java的内存泄漏和垃圾回收机制

    JAVA会产生内存泄露吗?首先,答案是肯定的. Java尽管有垃圾回收器,但依旧存在泄漏. Java内存泄漏跟C/C++内存泄漏的概念不一样:C/C++的内存泄漏是指Malloc了一些资源.最后没有f ...

  3. &lbrack; 转载 &rsqb; Java Jvm内存介绍

    一.基础理论知识 1.java虚拟机的生命周期: Java虚拟机的生命周期 一个运行中的Java虚拟机有着一个清晰的任务:执行Java程序.程序开始执行时他才运行,程序结束时他就停止.你在同一台机器上 ...

  4. 什么是内存溢出以及java中内存泄漏5种情况的总结

    内存泄漏定义(memory leak):一个不再被程序使用的对象或变量还在内存中占有存储空间. 一次内存泄漏似乎不会有大的影响,但内存泄漏堆积后的后果就是内存溢出.内存溢出 out of memory ...

  5. java jvm内存管理&sol;gc策略&sol;参数设置

    1. JVM内存管理:深入垃圾收集器与内存分配策略 http://www.iteye.com/topic/802638 Java与C++之间有一堵由内存动态分配和垃圾收集技术所围成的高墙,墙外面的人想 ...

  6. Java jvm 内存回收机制

    http://blog.csdn.net/yaerfeng/article/details/51291903 在Java中,它的内存管理包括两方面:内存分配(创建Java对象的时候)和内存回收,这两方 ...

  7. 排查JVM内存泄漏的命令

    1. jps 使用 jps -l -m 获取到当前jvm进程的pid,通过上述命令获取到了服务的进程号 jps(JVM Process Status Tool):显示指定系统内所有的HotSpot虚拟 ...

  8. MAT工具定位分析Java堆内存泄漏问题方法

    一.MAT概述与安装 MAT,全称Memory Analysis Tools,是一款分析Java堆内存的工具,可以快速定位到堆内泄漏问题.该工具提供了两种使用方式,一种是插件版,可以安装到Eclips ...

  9. Java提高篇—— 简单介绍Java 的内存泄漏

    java最明显的一个优势就是它的内存管理机制.你只需简单创建对象,java的垃圾回收机制负责分配和释放内存.然而情况并不像想像的那么简单,因为在Java应用中经常发生内存泄漏. 本教程演示了什么是内存 ...

随机推荐

  1. iOS网络3—UIWebView与WKWebView使用详解

    一.整体介绍 UIWebView自iOS2就有,WKWebView从iOS8才有,毫无疑问WKWebView将逐步取代笨重的UIWebView.通过简单的测试即可发现UIWebView占用过多内存,且 ...

  2. Codeforces Round &num;185 &lpar;Div&period; 2&rpar; A&period; Whose sentence is it&quest; 水题

    A. Whose sentence is it? Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/ ...

  3. 传智播客C语言视频第一季&lpar;有效下载期为10&period;1-10&period;7&comma;10&period;8关闭&rpar;

     J:\传智播客_尹成_C语言从菜鸟到高手├─传智播客_尹成_C语言从菜鸟到高手_第一章C语言概述A│      第一讲1.1C语言第一阶段.mp4│      第二讲1.2c语言入门教程.mp4 ...

  4. SQLServer 2008的组成

    SQLServer 2008的组成: 1.主要数据库文件:有且只有一个,文件后缀为.mdf. 2.日志文件:至少有一个,文件后缀为.ldf. 3.次要数据库文件:任意个,文件后缀为.ndf.

  5. Effective C&plus;&plus; 第二版 10&rpar; 写operator delete

    条款10 写了operator new就要同时写operator delete 写operator new和operator delete是为了提高效率; default的operator new和o ...

  6. 数据库之Oracle——初级

    世上岂无千里马,人中难得九方皋: 酒船鱼网归来是,花落故溪深一篙. 关于数据库的第一篇博客,这是我的第二次,人生第二春,什么也不想说,静静的开始吧,至于为什么写唐诗,请看第一篇文章! Oracle 初 ...

  7. iis读取不到本地证书问题

    导入证书时,通过mmc命令打开控制台->添加管理单元或删除单元->选择本地计算机账号->然后导入证书,解决 ssl证书无法与www.xxx通信. 证书导入后,不能正常读取.有两个问题 ...

  8. js函数库-D3

    推荐: https://www.cnblogs.com/createGod/p/6884629.html

  9. mssql sqlserver 快速表备份和表还原的方法

    摘要: 在sqlserver维护中,我们偶尔需要运行一些sql脚本对数据进行相关修改操作,在数据修改前我们必须对表数据进行备份来避免出现异常时,可以快速修复数据, 下文讲述sqlserver维护中,快 ...

  10. CCNA学前基础一

    网络设备: 集线器:集线器就是一种采用共享式工作状态的设备.Hub将信号放大后传输给其他端口,即传输线路是共享的. 交换机:用于连接终端设备,和基本的安全功能还有广播域的隔离.优点实现多用户同时访问, ...