这里,内存映像工具利用的是Eclipse Memory Analyzee,对Dump出来的堆转存储快照进行分析,能够分清楚究竟是出现了内存泄露(Memory Leak)仍是内存溢出(Memory Overflow)。java
在Eclipse中离线安装MemoryAnalyzee的步骤以下(因为在线安装可能会有网络问题):网络
(1)去官网下载离线安装包:app
即下载MemoyAnalyzer-1.6.1.201611251412.zip包。eclipse
(2)下载以后解压获得以下文件内容:jvm
(3)打开Eclipse->Help->Install new Software,以下:ide
将干菜下载好的路径引入其中。点击Ok。工具
(4)点击Avaliable Software Sites字体
注意:将里面,全部有关http链接的去掉勾选,不然,在更新的时候可能失败,以下:ui
只要location是http开头的就去勾选。spa
(5)去掉Contact all update sites during install to findrequired software前面的勾
(6)点击next,便可成功安装
那么:Eclipse Memory Analyzer如何使用呢?
为了使用MAT,即Memory Analyzer Tool,这里咱们使用的是Eclipse Memory Anaylyzer须要先明白内存分析的数据源是如何产生的。有两种方式:
(1)经过jmap(Memory Map for Java)命令生成堆转储快照(通常称为heapdump或dump文件)
(2)经过JVM参数 -XX:+HeapDumpOnOutOfMemoryError可让JVM在出现内存溢出异常时Dump出当前内存堆转存储快照以便过后进行分析。
这里先介绍第二种状况,即JVM中内存溢出后可以自动dump出对转存储快照。
编写一个简单的堆溢出的代码以下:
class User{
String name;
String sex;
@Override
public String toString() {
return "User [name=" + name + ", sex=" + sex + "]";
}
}
public class MemoryLeak1 {
public static void main(String[] args) {
List<User> list = new ArrayList<User>();
while(true){
list.add(new User());
}
}
}
分析:上面的代码中,经过List list中不断的添加new User()实例,由于list的做用域是和main方法同样的,而new出来的额User的实例被list中的元素引用,因此,经过while循环new 出来的User不会被GC。所以,致使内存溢出。
为了分析JVM中内存溢出的状况,须要添加JVM的参数:-XX:+HeapDumpOnOutOfMemoryError,操做步骤以下:
点击:Run->DebugConfiguration,在左侧列表下的Java Application下对应的你的Java类,好比:我这里的类是MemoryLeak1,以下:
在Arguments中的VM arguments下填写:-XX:+HeapDumpOnOutOfMemoryError,而后,点击Apply,以及点击Debug,即运行咱们以前写的那段会内存溢出的代码。在运行大概两三分钟以后,出现以下异常信息:
能够看到异常信息为java.lang.OutOfMemoryError:Java heap space,即内存溢出异常。上面的黑色字体是将内存堆转储为dump文件,这里的dump文件名称为:java_pid7568.hprof,其中7568是当前Java程序的进程号。
另外,须要注意的是刚才咱们生成的dump文件java_pid7568.hprof,这里的路径默认是在项目的根路径下,若是你没有看到该文件,须要强制刷新当前项目,好比:点击项目,而后按F5。
接下来,就是将该dump文件经过咱们上面的Memory Analyzer进行分析,步骤以下:
(1)在工具栏上:File->Open File…,选中java_pid7568.hprof文件,并打开
(2)可是产生了以下错误:
点击OK以后,有:
看了上述的问题,大体的意思是说内存溢出错误,后面又说了“Runngin Eclipse”,大体猜想应该是系统给Eclipse软件分配的内存过小,另外,咱们查看了java_pid7568.hprof文件的大小为3,355,137KB,大概是3g左右。因而,咱们又查看了Eclipse软件下的eclipse.ini文件:
那么eclipse.ini中的参数各是什么意思呢?在理解这些参数以前,须要知道Eclipse这款软件是由java语言开发的,所以,其自身也须要jvm支持的,那么它的默认参数配置就在eclipse.ini中,以下:
-startup
plugins/org.eclipse.equinox.launcher_1.3.100.v20150511-1540.jar
--launcher.library
plugins/org.eclipse.equinox.launcher.win32.win32.x86_64_1.1.300.v20150602-1417
-product
org.eclipse.epp.package.jee.product
--launcher.defaultAction
openFile
--launcher.XXMaxPermSize
512M
-showsplash
org.eclipse.platform
--launcher.XXMaxPermSize
512m
--launcher.defaultAction
openFile
--launcher.appendVmargs
-vmargs
-Dosgi.requiredJavaVersion=1.7
-Xms512m
-Xmx1024m
如上,咱们能够看到,Eclipse须要java 1.7版本的支持,通常咱们须要安装Jdk环境,假如咱们删除掉Jdk环境,那么会出现以下错误:
所以,Eclipse其实本质上就是一个Java程序,咱们能够经过JVM自带的jps命令来查看java进程,以下:
咱们输入jps发现进程id号为4316,与咱们在Windows任务管理器中看到的eclipse对应的PID是一致的,证实了咱们说的Eclipse本质上也是一个Java程序。
也须要设置最下的堆大小,这里默认是-Xms512m,最大的堆大小-Xmx1024m,显然最大的堆大小为1024m大概是1G左右,明显小于咱们要打开的文件3G的大小,这里,咱们将-Xmx设置5120m,以下:
-Dosgi.requiredJavaVersion=1.7
-Xms512m
-Xmx5120m
再次重启Eclipse,并打开咱们以前的那个大概3G左右的dump文件,则能够成功打开。
这里,主要看下“Histogram”,这个会列出每一个类的实例个数。以及“Leak Suspects”分析内存可能产生泄露的缘由。咱们看下:
Histogram:
这里Class Name是对应类型,Objects是对应实例的个数,很明显类com.tim.User的实例个数居然达到70,091,071个,那么后面跟着的两列:Shallow Heap和Retained Heap是什么东西?
问题:Shallow Heap和Retained Heap 的区别?
ShallowHeap:Shallow中文的意思是肤浅、浅的意思,则Shallow Heap咱们能够理解为浅的表面的堆,是对象自己占据的内存的大小,不包含其所引用的对象。
RetainedHeap:Retained中文的意思是保留、保存的意思,则Retained Heap咱们能够理解为保留、保存的堆,是当前对象大小+当前对象可直接或者间接引用到的对象的大小总和。
分析:上面的Shallow Heap是比较好理解的,而要真正理解Retained Heap须要先理解GC roots是如何工做的?
GCroots:
---------------------