一、使用jstat命令查看堆内存的使用情况
1、jstat 命令选项 vmid 间隔时间 查询次数
(1)查看当前进程Class类加载的统计
jstat -class
(2)查看编译统计
jstat -compiler
(3)查看垃圾回收统计
jstat -gc
s0c: 第一个Survivor区域大小
S1C:第二个Survivor区域的大小
S0U:第一个Survivor区域使用的大小
S1U:第二个Survivor区域使用的大小
EC:Eden区域的大小
EU:Eden区域的使用大小
OC:Old区的大小
OU:Old区使用的大小
MC:方法区大小
YGC:年轻代垃圾回收次数
FGC:年老代垃圾回收次数
2.通过jmap监控内存使用情况
(1)监控堆内存:jmap -heap
(2)监控内存中对象的数量及其大小:
(3)查看所有对象的数量以及大小包括类型:jmap -histo | more
(4)查看所有对象的数量以及大小包括类型:jmap -histo:live | more
(5)通过jmap导出堆内存使用情况的文件
jmap -dump:format=b,file=对应你的地址dump.dat 14116
(6)通过jhat查看dump文件并且进行分析,启动一个HTTP端口进行访问,通过该端口可以查看到整个应用程序所使用的的所有对象的情况,提供OQL进行检索
jhat -port 8081 对应你的地址dump.dat
访问效果如下
(1)
(2)
(3)
(4)
(5)
(6)
二、模拟内存溢出
1、模拟代码
public class HeapTest {
public static void main(String[] args){
List<Object> objList=new ArrayList<>();
for (int i=0;i<10000000;i++){
String str="";
for (int j=0;j<1000;j++){
str+= UUID.randomUUID().toString();
}
objList.add(str);
}
System.out.println("数据添加成功~");
}
}
2、在此设置参数
三、通过jstack监控JVM当中线程的运行情况 jstack 进程ID
线程抢占CPU资源,当CPU过高时,定位线程,查看线程使用状态
线程状态:
初始状态:New,线程对象创建出来后,没有调用start方法,线程处于初始状态
运行状态:
1.就绪状态:Ready,调用了Start方法,等待CPU分配资源
2.运行状态:RUNNING,CPU分配资源给该线程,该线程处于运行状态
阻塞状态 BLOCKED:
线程获取资源,如果资源获取成功则正常运行,如果资源获取失败,就处于阻塞状态,等待什么时候获取到资源再变为运行状态
等待状态 WAITING:线程手动调用了wait()方法,或者join()方法,这些方法都是主动进入等待状态,等待状态会将CPU资源让渡
需要其他线程手动唤醒,notify(),notifyAll()唤起所有的等待线程
超时等待状态 TIMED_WAITING:与等待状态相同,都是主动进入等待,也是需要其他线程唤醒,但是区别在与超时等待,如果超过了等待时间,则自动唤醒
Thread.sleep(2000),在休眠等待时间内会将CPU资源让渡,然后等待时间结束自动进入运行状态
终止状态DIED:线程结束之后的状态
四、手动模拟死锁情况
1、模拟代码
public class LockTest {
//定义资源
private static Object obj1=new Object();
private static Object obj2=new Object();
//线程1:先获取到资源1,然后休眠2s,在获取资源2
private static class ThreadA implements Runnable {
@Override
public void run() {
synchronized (obj1) {
System.out.println("ThreadA获取到了obj1资源");
try {
//休眠2s,因为我们要将CPU资源让渡出去,这样线程B就可以先抢占obj2资源
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (obj2) {
System.out.println("ThreadA获取到了obj2资源");
}
}
}
}
private static class ThreadB implements Runnable{
@Override
public void run() {
synchronized (obj2){
System.out.println("ThreadA获取到了obj2资源");
try {
//休眠2s,因为我们要将CPU资源让渡出去,这样线程B就可以先抢占obj2资源
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (obj1){
System.out.println("ThreadA获取到了obj1资源");
}
}
}
}
public static void main(String[] args){
new Thread(new ThreadA()).start();
new Thread(new ThreadB()).start();
}
}
2、实现效果如下
3、在控制台中效果如下
4、查看该文件