linux java性能监控工具_性能监控工具以及java堆分析OOM

一、性能监控工具

1.系统性能监控

Linux

-确定系统运行的整体状态,基本定位问题所在

-uptime:

9aa1e365344b019a33ed0907044ce779.png

------系统时间

------运行时间(例子中为127天)

------连接数(每个终端算一个连接)

------1,5,15分钟内的系统平均负载(运行队列中的平均进程数)

-top命令:动态查看进程变化,监控linux的系统状况

22995f3052be5a3e8a124a1536fd876b.png

-vmstat:显示虚拟内存状态(“Viryual Memor Statics”),但是它可以报告关于进程、内存、I/O等系统整体运行状态,如果CPU占用很高,上下文切换频繁,说明系统有现成正在频繁切换

0aea5c0a0bed3e46a038ad3787f1b57d.png

-pidstat:监控全部或指定进程占用系统资源的情况

------细致观察进程

------需要安装:sudo apt-get install sysstat

------监控CPU

------监控IO

------监控内存

pidstat –p 2962 –u 1 3 -t

-p指定进程号,-u监控CPU  1秒采样 一共3次、-t显式线程

b1c5446adccab0c91ac4db2d737fa76e.png

Windows

-Perfmon

------Windows自带多功能性能监控工具

c138e81c63735ddac86b1a371c509e67.png

15a34579984952ab6fcfba5d056cf47d.png

-Process Explorer(进程浏览器)

c02541261c2538dfbab6fe7dd584d228.png

-pslist(需要下载PSTOOLS)

------命令行工具,可用于自动化数据收集,显式java程序的运行情况

66e60c91b5a9c0af5479359b40feb2f1.png

2.java自带的工具

查看java程序运行细节,进一步定位问题

-jps:列出java进程,类似于ps命令

------参数-q可以指定jps只输出进程ID,不输出类的短名称

------参数-m可以用于输出传递给java进程(主函数)的参数

------参数-l可以用于输出主函数的完整路径

------参数-v可以显示传递给jvm的参数

9c216170456c0fdd0c4da37e0e4326be.png

-jinfo:用来查看正在运行的java应用程序的扩展参数,甚至支持在运行时,修改部分参数

------ -flag: 打印指定JVM参数值

------ -flag[+|-]:设置指定JVM参数的布尔值

------ -flag=:设置指定JVM参数的值

5a24d4431a8d129307004c5a0b38c595.png

-jmap:生成java应用程序的堆快照和对象的统计信息

------ jmap -histo 1536 >e:\project\JVM\s.txt

-Dump堆

------ jmap -dump:format=b,file=e:\project\JVM\heap.hprof 6900

3fb2be987c6dda4cdc7cee5d14b859b1.png

-jstack:打印线程dump

------ -l打印锁信息

------ -m 打印java和native的帧信息

------ -F 强制dump, 当jstack没有响应时使用

jstack 6900 >> e:\project\JVM\a.txt

5b20973c1f6ef0db973d429dd2545fa0.png

线程id号tid都是16进制

-JConsole

------图形化监控工具

------可以查看java应用程序的运行情况,监控堆信息,永久区使用情况,类加载等

-Visual VM

------是一个功能强大的多合一故障诊断和性能监控的可视化工具

二、java堆分析

1.内存溢出(OOM)的原因

-在jvm中,有哪些内存区间

------ 堆,永久区,线程栈,直接内存

------ 线程栈,是操作系统分配给jvm的一块内存区域,虽然说不在堆里面,但是这几块区域的总大小,不能超过操作系统能够分配给jvm的内存空间,一般32位系统,不能超过2g,当然肯定不能超过计算机的物理内存。

------ 如果上述四块内存区域,只要有一块申请的空间不能得到满足,那么就可能引起内存溢出(OOM)

------ 堆溢出

import java.util.ArrayList;

public class TestHeapOOM

{

public static void main(String[] args)

{

ArrayList list = new ArrayList();

for(int i = 0; i < 1024 * 1024; i++)

{

list.add(new byte[1 * 1024 * 1024]);

}

}

}

6d340bedfa7e9165e07c9269d70d5c34.png

占用大量堆空间,直接溢出--------解决:增大堆空间,及时释放内存

------永久区OOM(使用cglib进行测试,由于环境问题,没有做测试,就截了视频的图)

public class TestPerGenOOM{

public static void main(String[] args){

for(int i = 0; i < 100000; i++){

CglibBean bean = new CglibBean("****", new HashMap());

}

}

}

7d0b4d75f7cab645403c84fa5ba04949.png

解决方法:增大perm区,允许class原数据回收

------java栈溢出

这里的栈溢出指,在创建线程的时候,需要为线程分配栈空间,这个栈空间是向操作系统请求的,如果操作系统无法给出足够的空间,就会抛出OOM

操作系统可分配

堆空间

线程栈空间

public class TestStackOOM implements Runnable{

public void run(){

try{

Thread.sleep(10000000);

}catch(Exception e){

e.printStackTrace();

}

}

public static void main(String[] args){

for(int i = 0; i < 10000000; i++){

new Thread(new TestStackOOM(), "Thread" + 1).start();

System.out.println("Thread" + i + " created");

}

}

}

db31a8aaae46dade90a913511d0495dd.png

一直不会触发内存溢出 ,视频中是

Exception in thread ”main” java.lang.OutOfMemoryError;unable to create new native thread.

解决方法:减少堆内存,减少线程栈的大小(每个线程拥有线程栈,如果栈大小越小,那么在总空间一定的情况下,就能创建更多线程

)

------直接内存溢出(ByteBuffer.allocateDirect()无法从操作系统中获取足够空间)

操作系统可分配

堆空间

线程栈空间

直接内存

import java.nio.ByteBuffer;

public class TestDirectOOM

{

public static void main(String[] args)

{

for(int i = 0; i < 1024; i++){

ByteBuffer.allocateDirect(1024 * 1024);

System.out.println(i);

System.gc();

}

}

}

java -Xmx1g -XX:+PrintGCDetails TestDirectOOM

依然没有发生内存溢出,搞不清原因,截了视频的图

cbea17d11fb32b4a19140685f16e347e.png

f37a1225e384a0793426e1ef7f7ef25a.png

新生代,老年代都没有使用过多,基本可以断定是直接内存出问题

解决方法:减少堆内存,有意触发GC

2.支配树、浅堆、深堆

-浅堆:一个对象所占用的内存大小

浅堆(Shallow Heap)是指一个对象所消耗的内存。在32位系统中,一个对象引用会占据4个字节,一个int类型会占据4个字节,long型变量会占据8个字节,每个对象头需要占用8个字节。下面以String为例

07f824b4c1f590e37f84dd8052afecd3.png

2个int值共占8字节,对象引用占用4字节,对象头8字节,合计20字节,向8字节对齐,也就是8的倍数,故占24字节

这24字节为String对象的浅堆大小。它与String的value实际取值无关,无论字符串长度如何,浅堆大小始终是24字节

深堆:一个对象被GC回收后,可以真实释放的内存大小

了解深堆,首先需要了解保留集,对象A的保留集指当对象A被垃圾回收之后,可以被释放的所有对象的集合(包括对象A本身),即只能通过对象A被直接或间接访问到的所有对象的集合(包括A),被访问的对象入度为1,且这个1就是A或者A间接访问的对象。

----只能通过对象访问到的(直接或间接)所有对象的浅堆之和(支配树)

另外一个概念,对象的实际大小,定义为一个对象所能触及的所有对象的浅堆大小之和

539c3139c836fb1411e0634efd4d6e3f.png

上图中,A的浅堆大小只是A本身,不含C和D,而实际大小是ACD三者之和。而A的深堆大小为A与D之和,因为C还有B的引用。

支配树

8a79db9e10ed8a93cbefd8e089fc5d88.png

左图表示对象引用图,右图表示左图所对应的支配树。对象A和B由根对象直接支配,由于在到对象C的路径中,可以经过A,也可以经过B,因此对象C不能被A和B支配,所以它的直接支配者也是根对象。对象F与对象D相互引用,因为到对象F的所有路径必然经过对象D,因此,对象D是对象F的直接支配者。而到对象D的所有路径中,必然经过对象C,即使是从对象F到对象D的引用,从根节点出发,也是经过对象C的,所以,对象D的直接支配者为对象C;同理,对象E支配对象G。到达对象H的可以通过对象D,也可以通过对象E,因此对象D和E都不能支配对象H,而经过对象C既可以到达D也可以到达E,因此对象C为对象H的直接支配者。

支配者被回收,被支配对象也会被回收

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值