javavisualvm 怎么分析java 内存溢出出的原因

java(23)
jvm中除了程序计数器,其他的区域都有可能会发生内存溢出
内存溢出是什么?
当程序需要申请内存的时候,由于没有足够的内存,此时就会抛出OutOfMemoryError,这就是内存溢出
内存溢出和内存泄漏有什么区别?
内存泄漏是由于使用不当,把一部分内存“丢掉了”,导致这部分内存不可用。
当在堆中创建了对象,后来没有使用这个对象了,又没有把整个对象的相关引用设为null。此时垃圾收集器会认为这个对象是需要的,就不会清理这部分内存。这就会导致这部分内存不可用。
所以内存泄漏会导致可用的内存减少,进而会导致内存溢出。
用到的jvm参数
下面为了说明溢出的情景,会执行一些实例代码,同时需要给jvm指定参数
- -Xms 堆最小容量(heap min size)
- -Xmx 堆最大容量(heap max size)
- -Xss 栈容量(stack size)
- -XX:PermSize=size 永生代最小容量
- -XX:MaxPermSize=size 永生代最大容量
堆是存放对象的地方,那么只要在堆中疯狂的创建对象,那么堆就会发生内存溢出。
下面做一个堆溢出的实验
执行这段代码的时候,要给jvm指定参数
public class HeapOOMTest {
public static void main(String[] args){
LinkedList&HeapOOMTest& l=new LinkedList&HeapOOMTest&();
while(true){
l.add(new HeapOOMTest());
-Xms20m -Xmx20m作用是将jvm的最小堆容量和最大堆容量都设定为20m,这样就不会动态扩展jvm堆了
这段代码疯狂的创建对象,虽然对象没有声明变量名引用,但是将对象添加到队列l中,这样队列l就持有了一份对象的引用
通过可达性算法(jvm判断对象是否可被收集的算法)分析,队列l作为GC Root,每一个对象都是l的一个可达的节点,所以疯狂创建的对象不会被收集,这就是内存泄漏,这样总有一天堆就溢出了。
运行结果:
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at java.util.LinkedList.linkLast(Unknown Source)
at java.util.LinkedList.add(Unknown Source)
at test.HeapOOMTest.main(HeapOOMTest.java:23)
程序发生内存溢出,并提示发生在Java heap space
分析解决方法
用visualVM工具分析堆快照
如果发生内存泄漏:
step1:找出泄漏的对象
step2:找到泄漏对象的GC Root
step3:根据泄漏对象和GC Root找到导致内存泄漏的代码
step4:想法设法解除泄漏对象与GCRoot的连接
如果不存在泄漏:
1. 看下是否能增大jvm堆的最大容量
2. 优化程序,减小对象的生命周期
当发生堆溢出的时候,可以让程序在崩溃时产生一份堆内存快照
产生堆内存快照的方法:
给jvm加上参数XX:+HeapDumpOnOutofMemoryError,这样就会在程序崩溃的时候,产生一份堆内存快照
分析堆内存快照我建议用jdk自带的可视化监视工具visualVM,位置在jdk安装目录下的bin,如果是在linux环境的话,可以把快照传到window。因为分析工具会占用很大的内存,不建议在服务端进行分析。
下面对刚才程序产生的堆内存快照进行分析。
打开visualVM,装入刚刚生成的快照,打开类标签页
队列和疯狂创建的对象几乎占满了整个栈,想要让垃圾收集器回收这些对象,要让他们与GC Root断开连接
双击HeapOOMTest类,跳转到实例标签页,可以查看这个类的所有实例
在实例上右键——显示最近的垃圾回收根节点,可以看到这个对象与根节点的连接
只要断开HeapOOMTest对象与LinkedList的连接,这些疯狂创建的对象就会被收集了
调用方法的时候,会在栈中入栈一个栈帧,如果当前栈的容量不足,就会发生栈溢出StackOverFlowError
那么只要疯狂的调用方法,并且有意的不让栈帧出栈就可以导致栈溢出了。
下面来一次栈溢出
public class StackSOFTest {
public void stackLeak(){
stackLeak();
public static void main(String[] args){
StackSOFTest s=new StackSOFTest();
s.stackLeak();
jvm设置参数-Xss128k,目的是缩小栈的空间,这样栈溢出“来的快一点”
程序中用了递归,让栈帧疯狂的入栈,又不让栈帧出栈,这样就会栈溢出了。
运行结果:
Exception in thread "main" java.lang.StackOverflowError
at test.StackSOFTest.stackLeak(StackSOFTest.java:17)
at test.StackSOFTest.stackLeak(StackSOFTest.java:17)
运行时常量池溢出
这里储存的是一些常量、字面量。如果运行时常量池内存不足,就会发生内存溢出。从jdk1.7开始,运行时常量池移动到了堆中,所以如果堆的内存不足,也会导致运行时常量池内存溢出。
下面来一次运行时常量池溢出,环境是jdk8
只要创建足够多的常量,就会发生溢出
* jvm参数:
* jdk6以前:-XX:PermSize=10M -XX:MaxPermSize=10M
* jdk7开始:-Xms10m -Xmx10m
public class RuntimePoolOOM {
public static void main(String[] args){
LinkedList&String& l=new LinkedList&String&();
while(true){
l.add(String.valueOf(i++).intern());
因为jdk6以前,运行时常量池是在方法区(永生代)中的,所以要限制永生代的容量,让内存溢出来的更快。
从jdk7开始,运行时常量池是在堆中的,那么固定堆的容量就好了
这里用了链表去保存常量的引用,是因为防止被fullgc清理,因为fullgc会清理掉方法区和老年代
intern()方法是将常量添加到常量池中去,这样运行时常量池一直都在增长,然后内存溢出
运行结果:
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at java.lang.Integer.toString(Unknown Source)
at java.lang.String.valueOf(Unknown Source)
at test.RuntimePoolOOM.main(RuntimePoolOOM.java:30)
提示在heap区域发生内存溢出,果然运行时常量池被移到了堆中
方法区溢出
方法区是存放类的信息,而且很难被gc,只要加载了大量类,就有可能引起方法区溢出
这里将不做演示了,想试试的可以用cglib创建大量的代理类
工作中也有可能会遇上方法区溢出:
当多个项目都有相同jar包的时候,又都存放在WEB-INF\lib\下,这样每个项目都会加载一遍jar包。会导致方法区中有大量相同类(被不同的类加载器所加载),又不会被gc掉。
解决方案:
在应用服务器中建立一个共享lib库,把项目中常用重复的jar包存放在这里,项目从这里加载jar包,这样就会大大减少类加载的数量,方法区也“瘦身”了
如果实在不能瘦身类的话,那可以扩大方法区的容量,给jvm指定参数-XX:MaxPermSize=xxxM
查看原文:
&&相关文章推荐
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:34586次
排名:千里之外
原创:57篇
(5)(4)(6)(12)(14)(11)(7)
(window.slotbydup = window.slotbydup || []).push({
id: '4740887',
container: s,
size: '250,250',
display: 'inlay-fix'VisualVM 是一款免费的\集成了多个JDK 命令行工具的可视化工具,它能为您提供强大的分析能力,对 Java 应用程序做性能分析和调优。这些功能包括生成和分析海量数据、跟踪内存泄漏、监控垃圾回收器、执行内存和 CPU 分析,同时它还支持在 MBeans 上进行浏览和操作。
在内存分析上,Java VisualVM的最大好处是可通过安装Visual GC插件来分析GC(Gabage Collection)趋势、内存消耗详细状况。
一 &Visual GC(监控垃圾回收器)
Java VisualVM默认没有安装Visual GC插件,需要手动安装,JDK的安装目录的bin目露下双击jvisualvm.exe,即可打开Java VisualVM,点击菜单栏&工具-&插件&安装Visual GC
安装完成后重启Java VisualVM,Visual GC界面自动打开,即可看到JVM中堆内存的分代情况
被监控的程序运行一段时间后Visual GC显示如下
要看懂上面的图必须理解Java虚拟机的一些基本概念:
堆(Heap)&:JVM管理的内存叫堆
分代:根据对象的生命周期长短,把堆分为3个代:Young,Old和Permanent,根据不同代的特点采用不同的收集算法,扬长避短也。
Young(年轻代)年轻代分三个区。一个Eden区,两个Survivor区。大部分对象在Eden区中生成。当Eden区满时,还存活的对象将被复制到Survivor区(两个中的一个),当这个Survivor区满时,此区的存活对象将被复制到另外一个Survivor区,当这个Survivor去也满了的时候,从第一个Survivor区复制过来的并且此时还存活的对象,将被复制&年老区(Tenured)&。需要注意,Survivor的两个区是对称的,没先后关系,所以同一个区中可能同时存在从Eden复制过来对象,和从前一个Survivor复制过来的对象,而复制到年老区的只有从第一个Survivor复制过来的对象。而且,Survivor区总有一个是空的。
Tenured(年老代)年老代存放从年轻代存活的对象。一般来说年老代存放的都是生命期较长的对象。
Perm(持久代)用于存放静态文件,如今Java类、方法等。持久代对垃圾回收没有显著影响,但是有些应用可能动态生成或者调用一些class,例如Hibernate等,在这种时候需要设置一个比较大的持久代空间来存放这些运行过程中新增的类。持久代大小通过-XX:MaxPermSize=进行设置。
GC的基本概念
gc分为full gc 跟 minor gc,当每一块区满的时候都会引发gc。
Scavenge GC一般情况下,当新对象生成,并且在Eden申请空间失败时,就触发了Scavenge GC,堆Eden区域进行GC,清除非存活对象,并且把尚且存活的对象移动到Survivor区。然后整理Survivor的两个区。
Full GC对整个堆进行整理,包括Young、Tenured和Perm。Full GC比Scavenge GC要慢,因此应该尽可能减少Full GC。有如下原因可能导致Full GC:
上一次GC之后Heap的各域分配策略动态变化
System.gc()被显示调用
Perm域被写满
Tenured被写满
内存溢出&&out of memory,是指程序在申请内存时,没有足够的内存空间供其使用,出现out of memory;比如申请了一个integer,但给它存了long才能存下的数,那就是内存溢出。
内存泄露& memory leak,是指程序在申请内存后,无法释放已申请的内存空间,一次内存泄露危害可以忽略,但内存泄露堆积后果很严重,无论多少内存,迟早会被占光。其实说白了就是该内存空间使用完毕之后未回收。
二 Java VisualVM的其他功能
1.监视界面(cpu,类,堆,线程)
2.线程界面
3.Profile界面(性能剖析)
点击CPU按钮执行cpu分析查看方法
点击内存按钮执行内存分析查看类
4.堆dump和线程dump操作
Dump文件是进程的内存镜像,可以把程序的执行状态通过调试器保存到dump文件中,堆dump的dump文件内容如下图所示
阅读(...) 评论()Java程序内存分析Java VisualVM(Visual GC) - CSDN博客
Java程序内存分析Java VisualVM(Visual GC)
VisualVM 是一款免费的\集成了多个JDK 命令行工具的可视化工具,它能为您提供强大的分析能力,对 Java 应用程序做性能分析和调优。这些功能包括生成和分析海量数据、跟踪内存泄漏、监控垃圾回收器、执行内存和 CPU 分析,同时它还支持在 MBeans 上进行浏览和操作。在内存分析上,Java VisualVM的最大好处是可通过安装Visual GC插件来分析GC(Gabage Collection)趋势、内存消耗详细状况。一 &Visual GC(监控垃圾回收器)Java VisualVM默认没有安装Visual GC插件,需要手动安装,JDK的安装目录的bin目露下双击jvisualvm.exe,即可打开Java VisualVM,点击菜单栏 工具-&插件 安装Visual GC安装完成后重启Java VisualVM,Visual GC界面自动打开,即可看到JVM中堆内存的分代情况被监控的程序运行一段时间后Visual GC显示如下要看懂上面的图必须理解Java虚拟机的一些基本概念:堆(Heap) :JVM管理的内存叫堆分代:根据对象的生命周期长短,把堆分为3个代:Young,Old和Permanent,根据不同代的特点采用不同的收集算法,扬长避短也。Young(年轻代)年轻代分三个区。一个Eden区,两个Survivor区。大部分对象在Eden区中生成。当Eden区满时,还存活的对象将被复制到Survivor区(两个中的一个),当这个Survivor区满时,此区的存活对象将被复制到另外一个Survivor区,当这个Survivor区也满了的时候,从第一个Survivor区复制过来的并且此时还存活的对象,将被复制“年老区(Tenured)”。需要注意,Survivor的两个区是对称的,没先后关系,所以同一个区中可能同时存在从Eden复制过来对象,和从前一个Survivor复制过来的对象,而复制到年老区的只有从第一个Survivor复制过来的对象。而且,Survivor区总有一个是空的。参考文章:Tenured(年老代)年老代存放从年轻代存活的对象。一般来说年老代存放的都是生命期较长的对象。Perm(持久代)用于存放静态文件,如今Java类、方法等。持久代对垃圾回收没有显著影响,但是有些应用可能动态生成或者调用一些class,例如Hibernate等,在这种时候需要设置一个比较大的持久代空间来存放这些运行过程中新增的类。持久代大小通过-XX:MaxPermSize=进行设置。&&&& GC的基本概念gc分为full gc 跟 minor gc(Young GC也就是Minor GC),当每一块区满的时候都会引发gc。Scavenge GC一般情况下,当新对象生成,并且在Eden申请空间失败时,就触发了Scavenge
GC,堆Eden区域进行GC,清除非存活对象,并且把尚且存活的对象移动到Survivor区。然后整理Survivor的两个区。Full GC对整个堆进行整理,包括Young、Tenured和Perm。Full GC比Scavenge
GC要慢,因此应该尽可能减少Full GC。有如下原因可能导致Full GC:上一次GC之后Heap的各域分配策略动态变化System.gc()被显示调用Perm域被写满Tenured被写满内存溢出& out of memory,是指程序在申请内存时,没有足够的内存空间供其使用,出现out of memory;比如申请了一个integer,但给它存了long才能存下的数,那就是内存溢出。内存泄露& memory leak,是指程序在申请内存后,无法释放已申请的内存空间,一次内存泄露危害可以忽略,但内存泄露堆积后果很严重,无论多少内存,迟早会被占光。其实说白了就是该内存空间使用完毕之后未回收。查看java内存情况命令(jstat)&jmap -heap [pid] 查看内存分布&jstat -gcutil [pid] 1000 每隔1s输出java进程的gc情况JVM的GC简介和实例二 Java VisualVM的其他功能1.监视界面(cpu,类,堆,线程)2.线程界面VisualVM 的线程标签提供了三种视图,默认会以时间线的方式展现。另外两种视图分别是表视图和详细信息视图。时间线视图上方的工具栏提供了缩小,放大和自适应三个按钮,以及一个下拉框,我们可以选择将所有线程、活动线程或者完成的线程显示在视图中。3.Profile界面(性能剖析)在 Profiler 标签,点击“CPU”按钮启动一个 CPU 性能分析会话 ,VisualVM 会检测应用程序所有的被调用的方法。当进入一个方法时,线程会发出一个“method entry”的事件,当退出方法时同样会发出一个“method exit”的事件,这些事件都包含了时间戳。然后 VisualVM 会把每个被调用方法的总的执行时间和调用的次数按照运行时长展示出来。此外,我们也可以通过性能分析结果下方的方法名过滤器对分析结果进行过滤。点击内存按钮执行内存分析查看类4.快照功能我们可以使用 VisualVM 的快照功能生成任意个性能分析快照并保存到本地来辅助我们进行性能分析。快照为捕获应用程序性能分析数据提供了一个很便捷的方式因为快照一旦生成可以在任何时候离线打开和查看,也可以相互传阅。VisualVM 提供了两种类型的快照:Profiler 快照:当有一个性能分析会话(内存或者 CPU)正在进行时,我们可以通过性能分析结果工具栏的“快照”按钮生成 Profiler 快照捕获当时的性能分析数据。应用程序快照:我们可以右键点击左侧 Applications 窗口中应用程序节点,选择“应用程序快照”为生成一个应用程序快照。应用程序快照会收集某一时刻的堆转储,线程转储和 Profiler 快照,同时也会捕获 JVM 的一些基本信息。&Profiler 快照650) this.width=650;" alt="图 13. Profiler 快照" src="/developerworks/cn/java/j-lo-visualvm/nEO_IMG_image026.jpg" width="580" />应用程序快照650) this.width=650;" alt="图 14. 应用程序快照" src="/developerworks/cn/java/j-lo-visualvm/image028.gif" width="296" />5.堆dump(转储)和线程dump(转储)操作线程转储的生成与分析VisualVM 能够对正在运行的本地应用程序生成线程转储,把活动线程的堆栈踪迹打印出来,帮助我们有效了解线程运行的情况,诊断死锁、应用程序瘫痪等问题。堆转储的生成与分析VisualVM 能够生成堆转储,统计某一特定时刻 JVM 中的对象信息,帮助我们分析对象的引用关系、是否有内存泄漏情况的发生等。Dump文件是进程的内存镜像,可以把程序的执行状态通过调试器保存到dump文件中,堆dump的dump文件内容如下图所示当 VisualVM 统计完堆内对象数据后,会把堆转储信息显示在新的堆转储标签内,我们可以看到摘要、类、实例数等信息以及通过 OQL 【对象查询语言是专门为ODMG(Object Database Management Group)对象模型制定的查询语言】控制台执行查询语句功能。堆转储的摘要包括转储的文件大小、路径等基本信息,运行的系统环境信息,也可以显示所有的线程信息从类视图可以获得各个类的实例数和占用堆大小数,分析出内存空间的使用情况,找出内存的瓶颈,避免内存的过度使用。通过实例数视图可以获得每个实例内部各成员变量的值以及该实例被引用的位置。首先需要在类视图选择需要查看实例的类。此外,还能对两个堆转储文件进行比较。通过比较我们能够分析出两个时间点哪些对象被大量创建或销毁。线程转储和堆转储均可以另存成文件,以便进行离线分析。详细讲解:&本文出自 “” 博客,请务必保留此出处
本文已收录于以下专栏:
相关文章推荐
转自/developerworks/cn/java/j-lo-visualvm/
开发大型 Java 应用程序的过程中难免遇到内存泄露、性...
VisualVM 是一款免费的\集成了多个 JDK 命令行工具的可视化工具,它能为您提供强大的分析能力,对 Java 应用程序做性能分析和调优。这些功能包括生成和分析海量数据、跟踪内存泄漏、监控垃圾回...
1、安装JDK
    安装很简单,这里不再冗叙,测试JDK是否安装成功:在窗口命令中输入java -version测试之。
2、打开JavaVisualVM
在窗口命令中输入:jvisualvm...
VisualVM - JAVA 监控工具(8) 查找JAVA应用程序耗时的方法函数
那些方法函数需要监控
Java本身提供了多种丰富的方法和工具来帮助开发人员查看和分析GC及JVM内存的状况,同时开源界和商业界也有一些工具可用于查看、分析GC及JVM内存的状况。通过这些分析,可以排查程序中内存泄露的问题及...
一  、  VisualVM与eclipse集成、验证
1.1       到官网下载VisualVM包
2. 1      将visualvm_launcher_u1_eclipse_36.zi...
简单通俗的讲,一个完整的Java程序运行过程会涉及以下内存区域:
l 寄存器:JVM内部虚拟寄存器,存取速度非常快,程序不可控制。
l 栈:保存局部变量的值,包括:1.用来保存基本...
使用pmap查看进程内存
使用pmap可以查看某一个进程(非java的也可以)的内存使用使用情况,
命令格式:
pmap 进程id
例如运行:
pmap 12358
...
类的属性1.属性(field),或者叫成员变量
2.属性用于定义该类或该类对象包含的数据或者说静态属性
3.属性的作用范围是整个类体
4.**在定义成员变量时,可以对其初始化,如果不对其初始化,Jav...
JDK内置工具使用
一、javah命令(C Header and Stub File Generator)
二、jps命令(Java Virtual Machine Process Status ...
他的最新文章
讲师:吴岸城
您举报文章:
举报原因:
原文地址:
原因补充:
(最多只允许输入30个字)java内存溢出分析工具 - CSDN博客
java内存溢出分析工具
使用visualvm远程监控JVM&&
前段时间在排查问题过程中我使用了jprofiler远程进行了jvm资源使用情况的监控,从系统的损耗来看,jprofiler对系统资源尤其是内存的消耗是非常庞大的。当时配置的jprofiler内存使用上线是1G,后来发现系统内存在整个测试过程中出现持续上涨的趋势,最后稳定在3G左右(JVM的内存我们配的上限值是2G)。
从这个情况来看,如果我们要在测试过程中利用图形界面的形式实时监控jvm内存的使用情况,使用jprofiler是不合适的;在对几个性能测试工具进行评估后,我们最终选定了visualvm进行我们的java资源监控,下面我将讲述一下如何配置visualvm监控jvm资源以及在监控过程中visualvm在server上面的性能消耗情况
1.&如何配置visualvm监控
visualvm支持在linux和windows上启用图形界面监控jvm的资源,基于目前我们的server资源比较紧张,而且从监控方便的角度来分析(我们现有server的linux系统是关闭图形界面的,如果要支持visualvm的图形显示需要安装插件),我推荐在自己的windows环境中安装监控的客户端
Visualvm目前支持两种remote
connection方式,分别是jstatd和JMX方式;我看了一下官方的说明文档,如果是针对jboss的监控,官方还是推荐使用JMX的方式监控,因此下面我就讲述一下如何在server端以及客户端配置JMX方式监控的visualvm:
(1)首先要修改JDK中JMX服务的配置文件,以获得相应的权限:
进入$JAVA_HOME所在的根目录的/jre/lib/management子目录下,
a.&将jmxremote.password.template文件复制为jmxremote.password
b.&调整jmxremote.access和jmxremote.password的权限为只读写,可以使用如下命令
chmod 600 jmxremote.access jmxremote.password
c.&打开jmxremote.password文件,去掉
# monitorRole&QED
# controlRole&R&D
这两行前面的注释符号
(2)修改env.sh
打开env.sh文件,并在JVM的启动配置中添加如下信息:
JAVA_OPTS=&-Dcom.sun.management.jmxremote.port=1099 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false
-Djava.rmi.server.hostname=10.20.150.218&&其他配置”
这几个配置的说明如下:
-Dcom.sun.management.jmxremote.port:这个是配置远程connection的端口号的,要确定这个端口没有被占用
-Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false:这两个是固定配置,是JMX的远程服务权限的
-Djava.rmi.server.hostname:这个是配置server的IP的,要使用server的IP最好在机器上先用hostname
–i看一下IP是不是机器本身的IP,如果是127.0.0.1的话要改一下,否则远程的时候连不上,目前我们的server上我已经都改好了
(3)Windows客户端配置
JDK 1.6版本自带visualvm,只需要进到bin目录下启动即可
启动后页面比较简洁,配置也很简单:
a.&点击左侧菜单的add
Remote host,输入server的IP,然后再advanced
settings里配置端口(注意这个端口要和server上的端口一致)
b.&右击刚才配置的IP,选择JMX
connection方式,再次输入端口,就可以监视到JVM资源了,如下:
2. visualvm监控的资源消耗
我们配置了一个简单的apache+jboss应用,并用jmeter进行了一个长时间的加压,在加压过程中重点关注了系统资源的使用情况,如下(加压到9:30结束,另外cpu在最后一段出现了较大的毛刺是由于我在加压最后在server上用脚本处理数据导致,可以忽略该部分):
从长时间加压的结果来看,visualvm在监控过程中对cpu和load不会造成什么压力,这点同jprofiler一致;内存在加压过程中总计有1%左右的升高(稳定后)(系统内存是8G),表明visualvm对系统内存的消耗比jprofiler要低很多,在正常性能测试过程中如果开启visualvm监控对系统整体性能基本上没有影响(不要进行dump
heap的操作);当然,visualvm有一些功能相对jprofiler要简化一些,因此如果需要排查性能问题我还是推荐使用jprofiler
使用JDK 1.6自带的jvisualvm监控远程服务器中Java程序资源占用情况
因为做实验的需要,最近把实验室的Web数据抽取程序修改为多线程版本并在服务器上做大量的数据抽取工作,服务器是Ubuntu Server 10.01版本,通过Putty连接监控程序的运行情况非常不直观,需要使用一个Java资源监控程序实现对目标程序的实时监控。Jdk1.5版本提供的监控工具是Jconsole,相信很多早期的Java开发人员都使用过这个程序,但Jconsole的界面实在是有点对不起观众,所以在jdk1.6中Oracle提供了一个新的可视化的JVM监控工具Java
VisualVM(官方介绍链接:),在Windows系统下的Java
VisualVM启动路径是$java_home$/jdk1.6.0/bin/jvisualvm.exe。
&&&&&&双击启动Java VisualVM后可以看到窗口左侧“应用程序”栏中有“本地”、“远程”、“快照”三个项目。其中“本地”下显示的是在localhost运行的Java程序的资源占用情况,如果本地有Java程序在运行的话启动Java
VisualVM即可看到相应的程序名,点击程序名打开相应的资源监控菜单,以图形的形式列出程序所占用的CPU、Heap、PermGen、类、线程的统计信息。“远程”项下列出的远程主机上的Java程序的资源占用情况,但需要在远程主机上运行jstatd守护程序,下面就以实现对远程Ubuntu Server中运行的Java程序资源监控为例说明如何使用Java VisualVM监控远程Java程序。
&&&&&&(1)在服务器上安装jstatd组件。由于安装JDK时配置选项的原因,有的服务器中没有默认安装jstatd组件。jstatd是openjdk中的一个package,使用apt-get命令安装openjdk即可。关于jstatd组件的详细介绍可参考:
sudo apt-get install openjdk-6-jdk
&&&&&&(2)在服务器上配置jstatd的security policy文件。jstatd是一个监控JVM从创建到销毁过程中资源占用情况并提供远程监控接口的RMI(Remote Method Invocation,远程方法调用)服务器程序,它是一个Daemon程序,要保证远程监控软件连接到本地的话需要jstatd始终保持运行。jstatd运行需要通过-J-Djava.security.policy=***指定安全策略,因此我们需要在服务器上建立一个指定安全策略的文件jstatd.all.policy,文件内容如下:
grant codebase &file:${java.home}/../lib/tools.jar& {
permission java.security.AllP
&&&&&&(3)修改服务器hosts文件中的IP地址。要使Java VisualVM成功连接到远程服务器上,服务器端应该在/etc/hosts文件中把本机地址设为本机的IP地址。使用hostname -i命令查看,如果显示的是127.0.0.1或者与本机实际IP不一致的话,需要把/etc/hosts文件中相应的地址改为本机实际IP。
&&&&&&(4)运行jstatd守护程序。由于jstatd需要保持一直运行,所以建议使用screen命令执行jstatd程序,命令如下:
screen jstatd -J-Djava.security.policy=jstatd.all.policy
如果需要RMI日志功能的话,还可以在启动参数中加入-J-Djava.rmi.server.logCalls=true。jstatd开始运行后,使用CTRL+A+D断开screen界面,回到shell界面。如果想切换回jstatd运行界面的话,使用screen -r -d命令即可。
&&&&&&(5)通过Java VisualVM连接到服务器监控Java程序。在Java VisualVM程序窗口左侧“远程”项目右键选择“添加远程主机”,在弹出的对话框中输入远程主机的IP地址,确认提交后即可看到相应的远程主机和在上面运行的Java程序,连接成功后应该会显示Jstatd及其PID。
转载地址:
由于在建项目的需要,监控tomcat的内存使用,检查内存泄漏的情况。其实JDK自身已经提供了很多工具,都在JAVA_HOME/bin/目录下:jvisualvm、jconsole、jstatd、jmap等等,以下为试验的环境配置:&
client: vista、jdk1.6.0_18server: linux、jdk1.6.0_02、tomcat6、IP:192.168.8.7
主要从下面三个方面描述:&
jmap (Memory Map) JVM内存对象打印工具jstatd配置Tomcat配置JMX
一、用jmap获取数据&
JAVA_HOME/bin/jmap -histo PID&
JAVA_HOME/bin/jmap -histo PID &hismem.txt&
显示信息包括Java类、类实例对象数量、在内存中占有量的大小以及类的完整包名。&
//将JVM内存堆的信息dump成为一个二进制文件,可供jstat、Eclipse MAT内存分析工具来使用&
JAVA_HOME/bin/jmap -dump:format=b,file=heap.bin PID&
Eclipse MAT的分析工具:&
二:jstatd配置&
需要在被监控的服务器上面,通过jstatd来启动RMI服务。&
&&&& 新建个文件jstatd.all.policy 文件内容如下:&
Java代码&&
grant&codebase&&file:${java.home}/../lib/tools.jar&&{&&
&&&&permission&java.security.AllP&&
启动命令如下:&
Java代码&&
jstatd&-J-Djava.security.policy=jstatd.all.policy&&
jstatd&-J-Djava.rmi.server.hostname=192.168.8.7&&
-J-Djava.security.policy=test/jstatd.all.policy&&
jstatd&-J-Djava.rmi.server.hostname=192.168.8.7&&
-J-Djava.security.policy=test/jstatd.all.policy&-p&8888&&
jstatd&-J-Djava.rmi.server.hostname=192.168.8.7&&
-J-Djava.security.policy=test/jstatd.all.policy&&
-J-Dcom.sun.management.jmxremote.port=8888&&
-J-Dcom.sun.management.jmxremote.ssl=false&&
-J-Dcom.sun.management.jmxremote.authenticate=false&&
nohup&jstatd&-J-Djava.rmi.server.hostname=192.168.8.7&&
-J-Djava.security.policy=test/jstatd.all.policy&-p&8888&&&&
&&& 启动通过:netstat -an|grep 8888可以查看端口是否已经被监听&
&&& 用JAVA_HOME/bin/jmap 查看java进程:&
Java代码&&
jps&192.168.8.7&&
jps&rmi:&&
打开jvisualvm 界面如下:&
右击远程 选择添加远程主机:&
如果重新指定了jstatd端口,选择高级设置修改端口,如下图:&
如果同时配置了JMX,可以在添加JMX连接如下图:&
添加后如图所示:&
三:Tomcat配置JMX&
& 用hostname -i 查看是否为127.0.0.1,这步非常重要,否则会连接失败,如果是,必须要配置-Djava.rmi.server.hostname
比如我的配置为 -Djava.rmi.server.hostname=192.168.8.7,而不需要修改hosts文件,修改此文件还可能影响到其他程序。&
& 只需要在TOMCAT_HOME/bin/找到catalina.sh 加上以下参数,重新启动tomcat就可以了:&
JAVA_OPTS=&$JAVA_OPTS&-Djava.rmi.server.hostname=192.168.8.7&&
-Dcom.sun.management.jmxremote.port=8088&&
-Dcom.sun.management.jmxremote.ssl=false&&
-Dcom.sun.management.jmxremote.authenticate=false&&&
& 打开JAVA_HOME/bin/下的jvisualvm 或者jconsole 的工具可以直接连接了,如下图visualvm连接的示意图:&
& 也可以写个Java类TestJMXClient.java测试下JMX连接是否成功:
Java代码&&
import&java.util.HashM&&
import&java.util.M&&
import&javax.management.MBeanServerC&&
import&javax.management.remote.JMXC&&
import&javax.management.remote.JMXConnectorF&&
import&javax.management.remote.JMXServiceURL;&&
public&class&TestJMXClient&{&&
&&&&public&static&void&main(String[]&args)&{&&
&&&&&&&&try&{&&
&&&&&&&&&&&&String&jndiPath&=&&jmxrmi&;&&
&&&&&&&&&&&&String&serverhost&=&&192.168.8.7&;&&
&&&&&&&&&&&&String&serverport&=&&8088&;&&
&&&&&&&&&&&&&&
&&&&&&&&&&&&String&jmxurl&=&&service:jmx:rmi:///jndi/rmi://&&+&serverhost&+&&:&&&
&&&&&&&&&&&&&&&&&&&&+&serverport&+&&/&&+&jndiP&&
&&&&&&&&&&&&System.out.println(&jmxurl:&&+&jmxurl);&&
&&&&&&&&&&&&JMXServiceURL&url&=&new&JMXServiceURL(jmxurl);&&
&&&&&&&&&&&&Map&String,&Object&&enviMap&=&new&HashMap&String,&Object&();&&
&&&&&&&&&&&&JMXConnector&connector&=&JMXConnectorFactory.connect(url,&enviMap);&&
&&&&&&&&&&&&MBeanServerConnection&mbsc&=&connector.getMBeanServerConnection();&&
&&&&&&&&&&&&System.out.println(&successful&connected&&);&&
&&&&&&&&&&&&connector.close();&&
&&&&&&&&&&&&System.out.println(&close&connect&);&&
&&&&&&&&}&catch&(Exception&e)&{&&
&&&&&&&&&&&&System.out.println(&error&);&&
&&&&&&&&&&&&e.printStackTrace();&&
&&&&&&&&}&&
ps:JMX Management and Monitoring Properties&
com.sun.management.jmxremote
true / false. Default is true
com.sun.management.jmxremote. port
Port number. No default.
com.sun.management.jmxremote.ssl
true / false. Default is true.
com.sun.management.jmxremote.ssl.enabled.protocols
Default SSL/TLS protocol version.
com.sun.management.jmxremote.ssl.enabled.cipher.suites
Default SSL/TLS cipher suites.
com.sun.management.jmxremote.ssl.need.client.auth
true / false. Default is false
com.sun.management.jmxremote.authenticate
true / false.Default is true
com.sun.management.jmxremote.password.file
JRE_HOME/lib/management/jmxremote.password
com.sun.management.jmxremote.access.file
JRE_HOME/lib/management/jmxremote.access
com.sun.management.jmxremote.login.config
Default login configuration is a file-based password authentication.
转载地址:
本文已收录于以下专栏:
相关文章推荐
java内存溢出分析工具:jmap使用实战  
10:58:03|  分类:
rhel_apache |字号 订阅
在一次解决系统tomcat老...
java内存溢出性能分析工具讲解-- Eclipse Memory Analyzer tool(MAT)
java内存溢出分析工具:jmap使用实战  
10:58:03|  分类:rhel_apache
|字号 订阅
在一次解决系统tomcat老是内存撑到头,然后崩溃的问...
在使用Memory Analyzer tool(MAT)分析内存泄漏(一)中,我介绍了内存泄漏的前因后果。在本文中,将介绍MAT如何根据heap dump分析泄漏根源。由于测试范例可能过于...
问题发现:
在我们运行的一个项目上线运营后发现运行两天左右就会报内存溢出,只有重启tomcat才能恢复服务,异常信息如下:
java.lang.OutOfMemoryError: GC overh...
一、JProfiler简介
  JProfiler 是一个商业授权的Java剖析工具,由EJ技术有限公司,针对的Java EE和Java SE应用程序开发的。它把CPU、执行绪和内存的剖析组合在...
他的最新文章
讲师:吴岸城
您举报文章:
举报原因:
原文地址:
原因补充:
(最多只允许输入30个字)

我要回帖

更多关于 java 内存溢出 的文章

 

随机推荐