jmap dump文件分析分析的是堆内存还是栈内存

内存监控方法之——Jmap结合Memory&Analyzer,分析java程序是否存在内存泄漏
Jmap 是一个可以输出所有内存中对象的工具,甚至可以将VM 中的heap,以二进制输出成文本。
首先安装Eclipse环境:sudo apt-get
install eclipse
为Eclipse安装插件MAT:
(1)运行eclipse.
(2)通过 Help -& Software Updates...
启动软件更新管理向导。
(3)选择“Available Software“,然后,添加更新地址:
(4)接下来选择你想要安装的 MAT 的功能点,需要注意的是 Memory Analyzer (Chart)
这个功能是一个可选的安装项目,它主要用来生成相关的报表,不过如果需要用到这个功能,你还需要额外的安装 BIRT Chart
(5)插件安装完毕,重新启动 Eclipse 的工作平台。
使用MAT生成内存泄漏分析报告:
(1)通过jmap命令生成堆存储文件:jmap -F -dump:file=wxh.dmp
[pid]& //其中,wxh.dmp就是生成的堆存储文件。
&&& (2)打开Memory
Analyzer tool,然后选择菜单项 File- Open Heap Dump 来加载需要分析的堆转储文件。
(3)加载完成后,就可以点击工具栏上的 Leak Suspects 菜单项来生成内存泄露分析报告了。
那么,如何根据分析报告来分析内存的泄漏情况呢?
(1)查看内存消耗的整体情况
重点关注消耗内存最大的可疑对象。比如,是哪个类占用了绝大多数的内存,它属于哪个组件等等。
(2)分析问题所在&&&
首先我们简单回顾下JAVA 的内存回收机制,内存空间中垃圾回收的工作由垃圾回收器 (Garbage Collector,GC)
完成的,它的核心思想是:对虚拟机可用内存空间,即堆空间中的对象进行识别,如果对象正在被引用,那么称其为存活对象,反之,如果对象不再被引用,则为垃
圾对象,可以回收其占据的空间,用于再分配。
在垃圾回收机制中有一组元素被称为根元素集合,它们是一组被虚拟机直接引用的对象,比如,正在运行的线程对象,系统调用栈里面的对象以及被
system class loader
所加载的那些对象。堆空间中的每个对象都是由一个根元素为起点被层层调用的。因此,一个对象还被某一个存活的根元素所引用,就会被认为是存活对象,不能被
回收,进行内存释放。因此,我们可以通过分析一个对象到根元素的引用路径来分析为什么该对象不能被顺利回收。如果说一个对象已经不被任何程序逻辑所需要但
是还存在被根元素引用的情况,我们可以说这里存在内存泄露。
现在,让我们开始真正的寻找内存泄露之旅,点击“Details ”链接,可以看到对可疑对象的详细分析报告。
&&& (1)查看下从 GC
根元素到内存消耗聚集点的最短路径;
这时,可以很清楚的看到整个引用链,内存聚集点是一个拥有大量对象的集合,如果你对代码比较熟悉的话,相信这些信息应该能给你提供一些找到内存泄露的思路了。&&&
(2)接下来,再继续看,这个对象集合里到底存放了什么,为什么会消耗掉如此多的内存。
(3)至此,根据已经拥有的关于泄露点的信息,回到代码,找出是哪一段代码最终导致了内存泄露。
已投稿到:
以上网友发言只代表其个人观点,不代表新浪网的观点或立场。JVM内存状况查看方法和分析工具
Java本身提供了多种丰富的方法和工具来帮助开发人员查看和分析GC及JVM内存的状况,同时开源界和商业界也有一些工具可用于查看、分析GC及JVM内存的状况。通过这些分析,可以排查程序中内存泄露的问题及调优程序的性能。下面介绍几种常用的免费工具,其中知名的有JProfiler
  1. 输出GC日志
  输出GC日志对于跟踪分析GC的状况来说,无疑是最直接地分析内存回收状况的方法,只是GC日志输出后需要人为地进行分析,以判断GC的状况。
  JVM支持将输出到控制台或指定的文件中,方法有如下几种。
  输出到控制台
  在JVM的启动参数中加入-XX:+PrintGC -XX:+PrintGCDetails
-XX:+PrintGCTimeStamps
-XX:+PrintGCApplicationStoppedTime,按照参数的顺序分别输出GC的简要信息,GC的详细信息、GC的时间信息及GC造成的应用暂停的时间。
  输出到指定的文件
  在1中的jvm启动参数中再增加-Xloggc: gc.log可指定将gc的信息输出到gc.log中。
  可用于GC跟踪分析的参数还有-verbose:gc、-XX:+PrintTenuringDistribution等。
  2. GC Portal
  将GC日志输出固然有一定的作用,但如果要靠人为进行分析,还是相当复杂的。因此Sun提供了一个GC
Portal来帮助分析这些GC日志,并生成相关的图形化的报表,GC
Portal部署起来会有些麻烦,它需要运行在老版本的Tomcat上,同时需要,部署完毕后通过上传日志文件的方式即可完成GC日志的分析,此GC日志输出的JVM参数为:-verbose:gc
-XX:+PrintGCDetails -XX:+PrintGCTimeStamps [-Xloggc:文件名],在上传日志时GC
Portal的选项里只有jdk 1.2或jdk 1.2-1.4的版本。虽然经过,JDK
6的日志也是可以分析出来的,但它的限制在于仅支持5MB的gc日志的分析,GC
Portal可提供吞吐量的分析、耗费的CPU的时间、造成的应用暂停的时间、每秒从新生代转化到旧生代的数量、minor
GC的状况及Full GC的状况等,如图1所示。
图1& GCPortal示例
  GC Portal中还有一个很有用的部分是提供调整GC参数的预测,例如可以选择给young size增加20%的空间。GC
Portal会根据当前的日志信息来评估在调整参数后的运行效果,不一定很准确,但毕竟能带来一些参考意义。
3. JConsole
  JConsole可以图形化查看JVM中内存的变化状况,JConsole是JDK
5及以上版本中自带的工具,位于JDK的bin目录下,运行时直接运行JConsole.exe或JConsole.sh(要求支持图形界面)。在本地的Tab页上看到运行了java的pid,双击即可查看相应进程的JVM状况,同时,JConsole也支持查看远程的JVM的运行状况,具体可参见JConsole的User
  JConsole中显示了JVM中很多的信息:内存、线程、类和MBean等,在打开JConsole的内存Tab页后,可看到JVM内存部分的运行状况。这对于分析内存是否有溢出及GC的效果更加直接明了,JConsole的运行效果如图2所示。
图2& JConsole运行效果
  4. JVisualVM
  JVisualVM是JDK 6 update
7之后推出的一个工具,它类似于JProfiler的工具,基于此工具可查看内存的消耗情况、线程的执行状况及程序中消耗CPU、内存的动作。
  在内存分析上,JVisualVM的最大好处是可通过安装VisualGC插件来分析GC趋势、内存消耗详细状况。
  VisualGC的运行如图3所示。
图3& VisualGC运行效果
  从图3中可看到各区的内存消耗状况及GC Time的图表,其提供的Histogram视图对于调优也有很大帮助。
  基于JVisualVM的Profiler中的Memory还可查看对象占用内存的状况,如图4所示。
  JMap是JDK中自带的一个用于分析JVM内存状况的工具,位于JDK的bin目录下。使用JMap可查看目前JVM中各个代的内存状况、JVM中对象的内存的占用状况,以及导出整个JVM中的内存信息。
图4& JVisualVM Memory Profiler图示
  查看JVM中各个代的内存状况
  在linux上执行jmap -heap
[pid],就可查看整个JVM中内存的状况,看到的信息类似如下(和JDK版本、GC策略有关):
using&thread-local&object&allocation.
&Parallel&GC&with&8&thread(s)
&Heap&Configuration:
&&&&MinHeapFreeRatio&=&40&&&&MaxHeapFreeRatio&=&70&&&&MaxHeapSize&&&&&&=&&(1536.0MB)
&&&&NewSize&&&&&&&&&&=&&(500.0MB)
&&&&MaxNewSize&&&&&&&=&&(500.0MB)
&&&&OldSize&&&&&&&&&&=&4194304&(4.0MB)
&&&&NewRatio&&&&&&&&&=&8&&&&SurvivorRatio&&&&=&8&&&&PermSize&&&&&&&&&=&&(96.0MB)
&&&&MaxPermSize&&&&&&=&&(256.0MB)
&Heap&Usage:
&PS&Young&Generation
&Eden&Space:
&&&&capacity&=&&(410.75MB)
&&&&used&&&&&=&&(309.5MB)
&&&&free&&&&&=&&(101.5MB)
&&&&75.04%&used
&From&Space:
&&&&capacity&=&&(44.1875MB)
&&&&used&&&&&=&&(12.906MB)
&&&&free&&&&&=&&(31.094MB)
&&&&28.566%&used
&To&Space:
&&&&capacity&=&&(44.625MB)
&&&&used&&&&&=&0&(0.0MB)
&&&&free&&&&&=&&(44.625MB)
&&&&0.0%&used
&PS&Old&Generation
&&&&capacity&=&&(1036.0MB)
&&&&used&&&&&=&&(901.9MB)
&&&&free&&&&&=&&(134.1MB)
&&&&87.84%&used
&PS&Perm&Generation
&&&&capacity&=&&(96.0MB)
&&&&used&&&&&=&&(44.594MB)
&&&&free&&&&&=&&(51.406MB)
&&&&46.785%&used
从以上信息中可看出JVM堆的配置信息,如NewSize、NewRatio、SurvivorRatio等;JVM堆的使用情况,新生代中的Eden
Space、From Space、To Space的使用情况,旧生代和持久代的使用情况。
  要注意的是在使用CMS GC的情况下,jmap -heap的执行有可能会导致Java进程被挂起。
  JVM中对象的内存的占用情况
  在查看JVM内存状况时,除了要知道每个代的占用情况外,很多时候更要知道其中各个对象占用的内存大小,这样便于分析对象的内存占用情况,在分析OutOfMemory的场景中尤其适用。
  输入jmap -histo [pid]即可查看jvm堆中对象的详细占用情况,如图1所示。
图1& jmap -histo运行效果
  输出内容按照占用空间的大小排序,例如上面的[C,表示char类型的对象在jvm中总共有243 707个实例,占用了501
638 784 bytes的空间。
  导出整个JVM中的内存信息
  通过以上方法能查看到JVM中对象内存的占用情况,但很多时候还要知道这个对象到底是谁创建的。例如上面显示出来的[C,只知道它占用了那么多的空间,但不知道是什么对象创建出的[C,于是jmap提供了导出整个jvm中的内存信息的支持。基于一些jvm内存的分析工具,例如sun
JDK 6中的jhat、Eclipse Memory
Analyzer,可以分析jvm中内存的详细信息,例如[C是哪些对象创建的。
  执行如下命令即可导出整个jvm中的内存信息:
jmap&-dump:format=b,file=文件名&[pid]
  5. JHat
  JHat是Sun JDK 6及以上版本中自带的一个用于分析jvm堆dump文件的工具,基于此工具可分析jvm
heap中对象的内存占用状况、引用关系等。
  执行如下命令分析jvm堆的dump文件:
jhat&-J-Xmx1024M&[file]
  执行后等待console中输出Started HTTP
7000,看到后就可以通过浏览器访问http://ip:7000了,此页面默认为按package分类显示系统中所有的对象实例。在页面的最下端有Other
Queries导航,其中有显示jvm中对象实例个数的链接、有显示jvm中对象大小的链接等,点击显示jvm中对象大小的链接,得到的结果如图2所示。
图2& jhat运行效果
  点击图2中的class
[C,可以看到有哪些对象实例引用了这个对象,或者创建了这个对象,jhat在分析大的堆dump文件时表现不好,速度很慢。
  JStat是Sun
JDK自带的一个统计分析JVM运行状况的工具,位于JDK的bin目录下,除了可用于分析GC的状况外,还可用于分析编译的状况、class加载的状况等。
  JStat用于GC分析的参数有:-gc、-gccapacity、-gccause、-gcnew、-gcnewcapacity、-gcold、-gcoldcapacity、-gcpermcapacity、-gcutil。常用的为-gcutil。通过-gcutil可按一定频率查看jvm中各代的空间的占用情况、minor
GC的次数、消耗的时间、full GC的次数及消耗的时间的统计,执行jstat -gcutil [pid]
[interval],可看到类似如下的输出信息:
&S0&&&&&S1&&&&&&&E&&&&&&O&&&&&&&P&&&&&&&YGC&&&
YGCT&&&&&FGC&&&&FGCT&&&&&GCT
&&0.00&&&74.24&&96.73&&73.43&&46.05&&17808&&
382.335&&&208&&315.197&&697.533
&45.37&&&0.00&&&28.12&&74.97&&46.05&&17809&
382.370&&&208&&315.197&&697.568
  其中S0、S1就是Survivor空间的使用率,E表示Eden空间的使用率,O表示旧生代空间的使用率,P表示持久代的使用率,YGC表示minor
GC的执行次数,YGCT表示minor GC执行消耗的时间,FGC表示Full GC的执行次数,FGCT表示Full
GC执行消耗的时间,GCT表示Minor GC+Full GC执行消耗的时间。
  7. Eclipse Memory Analyzer
  Eclipse Memory
Analyzer是Eclipse提供的一个用于分析jvm堆dump文件的插件,借助这个插件可查看对象的内存占用状况、引用关系、分析内存泄露等。
  Eclipse Memory Analyzer(MAT)的网站为:http://www.eclipse.org/mat/,在eclipse中可以直接远程安装此插件。不过由于此插件在分析堆dump文件时比较耗内存,因此在分析前最好先将eclipse的jvm的内存设置大一点,MAT分析dump文件后的对象占用内存及引用关系如图3所示。
  相对而言MAT功能比jhat强大很多,分析的速度也快一些,因此,如果要分析jvm堆dumap文件,首选推荐的是MAT。
  在进行JVM内存状况分析时,通常要关注的主要有GC的趋势、内存的具体消耗状况。
  GC趋势对于可图形界面连到需查看GC状况的机器的情况而言,VisualVM是常用的选择;对于不能采用图形界面方式的,输出GC日志
及采用jstat命令直接分析是常用的选择。
  在查找内存是程序中的什么对象占用时,需要分析内存的具体消耗状况,对于有图形界面可用的情况,VisualVM是常用的选择;对于不能采用图形界面方式的,可通过jmap
dump生成文件后,再通过MAT进行分析是常用的选择。
图3& MAT运行效果
已投稿到:
以上网友发言只代表其个人观点,不代表新浪网的观点或立场。后使用快捷导航没有帐号?
查看: 1690|回复: 3
JVM内存溢出问题总结
注册会员, 积分 171, 距离下一级还需 29 积分
论坛徽章:5
JVM的内存溢出问题,是个常见而有时候有非常难以定位的问题。定位内存溢出问题常见方法有很多,但是其实很多情况下可供你选择的有效手段非常有限。很多方法在一些实际场景下没有实用价值。这里总结下我的一些定位思路。
要定位JVM内存溢出问题,首先要对JVM的内存布局有一定的了解,对常见的JVM内存工具要比较熟悉。所谓工欲善其事,必先利其器。而熟悉JVM的内存管理机制是你定位JVM内存问题的基石。首先介绍下JVM的内存管理机制:
程序和C类程序一个重要的区别就是JAVA中的内存回收管理工作有JVM完成,而不需要为程序中的每个new/malloc去delete/free。那JVM这么智能怎么还有内存溢出问题呢,一个常见的原因是我们的JAVA程序中长时间的持有了不该持有的对象,或者申请了过多的对象使得JVM的内存不够用。
JVM管理的几个内存区域包括以下几个内存区域:
1、&&方法区:用于存储JAVA类信息、常量、静态变量。这个区域也可以发生垃圾回收,比如当一些类不在被引用时JVM可以卸载这个类,不过这种回收动作很少发生。另外所有线程都共享方法区,因此线程对方法区的访问被设计为线程安全的。
2、&&虚拟机栈:JAVA虚拟机栈是线程私有的,每当启动一个新线程时,JVM都会为它分配一个JAVA虚拟机栈。没当线程调用方法时,JVM都会为虚拟机栈压入一个栈帧,该栈帧用于存储参数、局部变量、中间运算结果、方法出口等。
3、&&本地方法栈:和虚拟机栈类似,只是他是专为JAVA中的Native方法服务。当线程进入本地方法后,它已经脱离的JVM的限制,甚至可以直接使用本地处理器中的寄存器。实际上本地方法的调用机制非常依赖于JVM的具体实现。
4、&&堆:由JVM启动时创建,由所有线程共享,用于存放对象的实例。一般情况下它是JVM中管理的内存中最大的一块。绝大部分JVM内存问题都发生在这一块。
5、&&程序计数器:同虚拟机栈一样,它也是线程私有,启动线程是创建。程序计数器的中保存的内容总是下一条将被执行的指令的地址。
这几个内存区域,除了程序计数器区域外,其他几个区域都有可能发生内存溢出问题。常见的内存溢出有两种:
1、方法区溢出。出现该问题时,JVM会报如下类似错误:java.lang.OutOfMemoryError : PermGenSpace ,Perm区的最大内存大小可以通过-XX:MaxPermSize=指定。引起这类内存溢出原因一般有两个,一个是常量池太大,一个是需要加载的CLASS类太多。出现问题的时候排查下这两种可能性,问题可以很快找到。这类问题程序稳定后也很少出现。
2、堆内存溢出。在JVM可使用的最大堆内存可以在启动的时候通过-Xmx参数指定。堆内存溢出是最为常见的内存溢出问题,发生堆内存溢出时,JVM会报告如下错误:java.lang.OutOfMemoryError : java heap space。
这里列举下在定位堆内存溢出时,常见的方法和思路。堆内存溢出顾名思义就是,堆内存不够用了,如果程序设计的最大对内存已经耗尽,那说明程序设计存在问题,不该申请很多内存的逻辑申请了很多的内存,该释放的对象没有释放。最重要的问题是就要要找出到底是什么对象没有及时释放,导致占用了过多的内存。常见的方法:
a、&&一个强大的定位工具是使用 jprofiler,通过jprofiler可以实时的监控到,当前的堆内存的总体使用情况及当前存活的对象、大小、分配树、对象引用链等等,功能非常全面。如下图所示:
通过该工具还可以实时的生成堆内存快照,然后通过不同时间点生成的内存快照做比较已确定内存增长点。但是实际使用中如果程序征程运行中占用的内存就比较高,比如800M左右,而在32位机器上,JVM可以使用的最高内存在1280M左右,如果应用程序设置的最大堆内存是1024M,那么实际即将发生堆内存溢出时,程序使用的内存是处一个比较高的位置。这时候通过jprofiler监控效果就很不理想,我在windows server 2003 32位服务器上做测试,想通过jprofiler监控一个TOMCAT应用程序,该应用程序常态中占用内存在800M左右,启用jprofiler监控后,jprofiler监控程序本身就会变得很不稳定,常常莫名挂死(通过jprofiler监控应用程序的时候实际上上jprofiler对应用程序又做了一层包装后启动的,因此jprofiler监控程序挂死,等于被监控的程序挂死)。很难抓取到有用的信息。
因此jprofiler在32位机器上只适用用小内存应用程序。
b、&&使用JVM自带的jmap工具导出堆信息分析,这个工具可以通过如下命令到处自定的JVM进程的堆内存:jmap –dump:format=b,file=heap.bin &pid&&&。
但这个工具也有一样的问题,在应用程序使用的内存处于高位时,使用jmap导出堆信息会出现空间不足,无法导出的问题。Java自带的很多工具都有类似的限制,所以实际上你的选择并不多。
c、&&在启动JVM的时候加上以下两个参数:
-XX:HeapDumpPath=./dumpfile.hprof
-XX:+HeapDumpOnOutOfMemoryError
表示出现OOM错误后,将堆信息dump出来。不过这个参数也有个问题,在实际使用的时候发现在windows平台上,如果程序是以TOMCAT服务的方式运行,出现OOM错误后堆信息也dump不出来。
d、&&通过visualVM程序监控JVM,JDK 1.6中自带的可视化监控工具,这个工具比较实用,功能也比较强大。可以监控线程信息,堆内存信息,还可以实时导出堆信息以及强制GC。监控本地JVM直接启动该工具后就可以监控,远程监控需要启动jstatd和jrxml。
启动jstatd方法:新建jstatd.all.policy文件,添加如下内容,tools.jar包的路径根据实际情况修改:
grant codebase &file:/home/ndmc/tomcat/jdk/jre/lib/tools.jar& {
& &permission java.security.AllP
执行启动命令./jstatd -J-Djava.security.policy=jstatd.all.policy,默认端口为1099,后面可跟-p指定其他端口号
使用jrxml远程监控JVM的时候需要加上以下参数:
-Dcom.sun.management.jmxremote
-Dcom.sun.management.jmxremote.port=8849
-Dcom.sun.management.jmxremote.ssl=false
-Dcom.sun.management.jmxremote.authenticate=false
-Djava.rmi.server.hostname=hostip
监控效果如下:
在监控过程中可以手动的GC和DUMP堆内存,还可以设置Heap dump on OOME: enabled,使得在堆内存溢出的时候可以dump heap。不过根据实际使用,建议最高在堆内存即将溢出的时候就应该手动dump heap,因为等到OOM的时候常常程序已经挂死,heap已经导不出来了。
e、&&导出dump信息后就可以通过jprofiler工具或者HeapAnalyzer做分析。这两个工具都很强大,网上有很多的使用指导。可以初步分析出到底是什么对象在占用内存,以及相应的引用链,到这一步在结合源代码在定位内存溢出问题就相对容易了。&&
总结:定位内存溢出问题需要一个冷静的头脑、敏锐的观察能力、缜密的分析问题能力。甚至常常需要根据一些现象做猜测然后验证,找出最后的元凶,有可能内存的溢出是有多个方面引起的:代码BUG、软件设计问题、网络的吞吐量以及网路连接问题、数据库问题等都可能是相关需要排查的因素,甚至有时候可能是操作系统或者JVM本身存在的BUG导致。而能够在JVM堆内存即将溢出的时候导出堆信息是问题定位的关键,只要能够导出堆信息,一系列的猜测、分析是否正确就有可靠的证据。
金牌会员, 积分 1008, 距离下一级还需 1992 积分
论坛徽章:17
总结的很犀利啊!期待你以后的文章。
新手上路, 积分 6, 距离下一级还需 44 积分
论坛徽章:1
总结的很犀利啊!期待你以后的文章。+1
中级会员, 积分 338, 距离下一级还需 162 积分
论坛徽章:4
多谢分享,收藏之后慢慢看。Java堆内存的10个要点
发表于 09:06|
来源伯乐在线|
作者唐小娟
摘要:对大多数程序员都经历过这样的过程,因为学习一种语言是非常容易来的,但是学习基础是非常难的,因为没有什么特定的流程让你学习编程的每个基础,使你发觉编程的秘诀。
导读:对于程序员来说,知道堆空间,设置堆空间,处理堆空间的outOfMemoryError错误,分析heap dump是非常重要的。文中介绍了Java堆的学习教程以及Java堆内存(heap memory)的十个要点。
文章内容如下:
我刚开始学习Java编程时,可不知道什么是堆内存或堆空间(heap space),甚至根本不管对象创建时都放在哪里去了。正式了写一些程序后,经常会遇到java.lang.outOfMemoryError等错误,我才开始关注堆内存。
对大多数程序员都经历过这样的过程,因为学习一种语言是非常容易来的,但是学习基础是非常难的,因为没有什么特定的流程让你学习编程的每个基础,使你发觉编程的秘诀。
对于程序员来说,知道堆空间,设置堆空间,处理堆空间的outOfMemoryError错误,分析heap dump是非常重要的。这个关于Java堆的教程是给我刚开始学编程的兄弟看的。如果你知道这个基础知识或者知道底层发生了什么,当然可能帮助不是那么大。除非你知道了对象被创建在堆中,否则你不会意识到OutOfMemoryError是发生在堆空间中的。我尽可能的将我所知道的所有关于堆的知识都写下来了,也希望你们能够尽可能多的贡献和分享你的知识,以便可以让其他人也受益。
Java中的堆空间是什么?
当Java程序开始运行时,JVM会从操作系统获取一些内存。JVM使用这些内存,这些内存的一部分就是堆内存。堆内存通常在存储地址的底层,向上排列。当一个对象通过new关键字或通过其他方式创建后,对象从堆中获得内存。当对象不再使用了,被当做垃圾回收掉后,这些内存又重新回到堆内存中。要学习垃圾回收,请阅读&Java中垃圾回收的工作原理&。
如何增加Java堆空间
在大多数32位机、Sun的JVM上,Java的堆空间默认的大小为128MB,但也有例外,例如在32未Solaris操作系统(SPARC平台版本)上,默认的最大堆空间和起始堆空间大小为 -Xms=3670K 和 -Xmx=64M。对于64位操作系统,一般堆空间大小增加约30%。但你使用Java 1.5的throughput垃圾回收器,默认最大的堆大小为物理内存的四分之一,而起始堆大小为物理内存的十六分之一。要想知道默认的堆大小的方法,可以用默认的设置参数打开一个程序,使用JConsole(JDK 1.5之后都支持)来查看,在VM Summary页面可以看到最大的堆大小。
用这种方法你可以根据你的程序的需要来改变堆内存大小,我强烈建议采用这种方法而不是默认值。如果你的程序很大,有很多对象需要被创建的话,你可以用-Xms and -Xmx这两个参数来改变堆内存的大小。Xms表示起始的堆内存大小,Xmx表示最大的堆内存的大小。另外有一个参数 -Xmn,它表示new generation(后面会提到)的大小。有一件事你需要注意,你不能任意改变堆内存的大小,你只能在启动JVM时设定它。
堆和垃圾回收
我们知道对象创建在堆内存中,垃圾回收这样一个进程,它将已死对象清除出堆空间,并将这些内存再还给堆。为了给垃圾回收器使用,堆主要分成三个区域,分别叫作New Generation,Old Generation或叫Tenured Generation,以及Perm space。New Generation是用来存放新建的对象的空间,在对象新建的时候被使用。如果长时间还使用的话,它们会被垃圾回收器移动到Old Generation(或叫Tenured Generation)。Perm space是JVM存放Meta数据的地方,例如类,方法,字符串池和类级别的详细信息。你可以查看&Java中垃圾回收的工作原理&来获得更多关于堆和垃圾回收的信息。
Java堆中的OutOfMemoryError错误
当JVM启动时,使用了-Xms 参数设置的对内存。当程序继续进行,创建更多对象,JVM开始扩大堆内存以容纳更多对象。JVM也会使用垃圾回收器来回收内存。当快达到-Xmx设置的最大堆内存时,如果没有更多的内存可被分配给新对象的话,JVM就会抛出java.lang.outofmemoryerror,你的程序就会当掉。在抛出 OutOfMemoryError之前,JVM会尝试着用垃圾回收器来释放足够的空间,但是发现仍旧没有足够的空间时,就会抛出这个错误。为了解决这个问题,你需要清楚你的程序对象的信息,例如,你创建了哪些对象,哪些对象占用了多少空间等等。你可以使用profiler或者堆分析器来处理 OutOfMemoryError错误。&java.lang.OutOfMemoryError: Java heap space&表示堆没有足够的空间了,不能继续扩大了。&java.lang.OutOfMemoryError: PermGen space&表示permanent generation已经装满了,你的程序不能再装在类或者再分配一个字符串了。
Java Heap dump
Heap dump是在某一时间对Java堆内存的快照。它对于分析堆内存或处理内存泄露和Java.lang.outofmemoryerror错误是非常有用的。在JDK中有一些工具可以帮你获取heap dump,也有一些堆分析工具来帮你分析heap dump。你可以用&jmap&来获取heap dump,它帮你创建heap dump文件,然后,你可以用&jhat&(堆分析工具)来分析这些heap dump。
Java堆内存(heap memory)的十个要点:
1. Java堆内存是操作系统分配给JVM的内存的一部分。
2. 当我们创建对象时,它们存储在Java堆内存中。
3. 为了便于垃圾回收,Java堆空间分成三个区域,分别叫作New Generation, Old Generation或叫作Tenured Generation,还有Perm Space。
4. 你可以通过用JVM的命令行选项 -Xms, -Xmx, -Xmn来调整Java堆空间的大小。不要忘了在大小后面加上&M&或者&G&来表示单位。举个例子,你可以用 -Xmx256m来设置堆内存最大的大小为256MB。
5. 你可以用JConsole或者 Runtime.maxMemory(), Runtime.totalMemory(), Runtime.freeMemory()来查看Java中堆内存的大小。
6. 你可以使用命令&jmap&来获得heap dump,用&jhat&来分析heap dump。
7. Java堆空间不同于栈空间,栈空间是用来储存调用栈和局部变量的。
8. Java垃圾回收器是用来将死掉的对象(不再使用的对象)所占用的内存回收回来,再释放到Java堆空间中。
9. 当你遇到java.lang.outOfMemoryError时,不要紧张,有时候仅仅增加堆空间就可以了,但如果经常出现的话,就要看看Java程序中是不是存在内存泄露了。
10. 请使用Profiler和Heap dump分析工具来查看Java堆空间,可以查看给每个对象分配了多少内存。
文章出自:&(无法直接访问)
译文出自:
推荐阅读相关主题:
网友评论有(0)
CSDN官方微信
扫描二维码,向CSDN吐槽
微信号:CSDNnews
相关热门文章

我要回帖

更多关于 jmap 内存分析 的文章

 

随机推荐