JVM基本介绍以及参数优化
1.JVM的基本结构
黄色为线程共享区
蓝色为线程独占区
别名非堆 , 存放静态变量+常量+类信息(构造方法+接口信息)+运行时常量池
用于存放对象实例 , 所有的对象都会在堆上分配内存;
堆内存分为新生代,老年代,原空间;
- 差不多占用堆内存的1/3;
- 新生代分为 Eden, From, To区 , From和To区统称为Survivor区;
- 新对象一般会放在Eden区, 如果Eden区放满 , 会出现Young GC(Minor GC),耗时短 , 回收Eden中对象转移进入Survivor区,在Survivor区的对象会在From区和To区循环转移 , 直到进行到第15次时 , 对象会进行老年代转移
- 差不多占用堆内存的2/3;
- 对象过大会直接进入老年代 , 并且在Survivor转移次数过多的对象也会进入;
- 如果老年代内存耗尽 , 会进行Full GC(Major GC),特点次数多,耗时长,原因是因为进行Full GC时会停止其他用户线程
Java8内存模型—永久代(PermGen)和元空间(Metaspace)l
使用命令
javap -v xxx.class > xxx.txt
输出附加信息到xxx.txt
栈中存储的是栈帧
栈帧由 局部变量 操作数栈 动态链接 方法出口 构成
说白了就是C++代码库
PC 寄存器,也叫程序计数器。JVM支持多个线程同时运行,每个线程都有自己的程序计数器。倘若当前执行的是 JVM 的方法,则该寄存器中保存当前执行指令的地址;倘若执行的是native 方法,则PC寄存器中为空。
2.JDK性能监测工具
监测工具
- Jps : 主要用来输出JVM中运行的进程状态信息
参数说明 :
-q 不输出类名、Jar名和传入main方法的参数
-m 输出传入main方法的参数
-l 输出main类或Jar的全限名
-v 输出传入JVM的参数
- Jinfo : 打印JVM参数
- Jstat : JVM统计监测工具
- Jmap : 用来查看堆内存使用状况
jmap -permstat pid # 打印进程的类加载器和类加载器加载的持久代对象信息,输出:类加载器名称、对象是否存活(不可靠)、对象地址、父类加载器、已加载的类大小等信息
jmap -heap pid # 查看进程堆内存使用情况,包括使用的GC算法、堆配置参数和各代中堆内存使用情况
jmap -histo[:live] # pid查看堆内存中的对象数目、大小统计直方图,如果带上live则只统计活对象
- JHat : 分析dunp文件
语法格式如下 : jstat [ generalOption | outputOptions vmid [interval[s|ms] [count]] ]
vmid是虚拟机ID,在Linux/Unix系统上一般就是进程ID。interval是采样时间间隔。count是采样数目。比如下面输出的是GC信息,采样时间间隔为250ms,采样数为4:
- Jstack : 主要用来查看某个Java进程内的线程堆栈信息
New: 当线程对象创建时存在的状态,此时线程不可能执行;
Runnable:当调用thread.start()后,线程变成为Runnable状态。只要得到CPU,就可以执行;
Running:线程正在执行;
Waiting:执行thread.join()或在锁对象调用obj.wait()等情况就会进该状态,表明线程正处于等待某个资源或条件发生来唤醒自己;
Timed_Waiting:执行Thread.sleep(long)、thread.join(long)或obj.wait(long)等就会进该状态,与Waiting的区别在于Timed_Waiting的等待有时间限制;
Blocked:如果进入同步方法或同步代码块,没有获取到锁,则会进入该状态;
Dead:线程执行完毕,或者抛出了未捕获的异常之后,会进入dead状态,表示该线程结束
其次,对于jstack日志,我们要着重关注如下关键信息
Deadlock:表示有死锁
Waiting on
condition:等待某个资源或条件发生来唤醒自己。具体需要结合jstacktrace来分析,比如线程正在sleep,网络读写繁忙而等待
Blocked:阻塞
Waiting on monitor entry:在等待获取锁
in Object.wait():获取锁后又执行obj.wait()放弃锁
对于Waiting on monitor entry 和 in Object.wait()的详细描述:Monitor是
Java中用以实现线程之间的互斥与协作的主要手段,它可以看成是对象或者 Class的锁。每一个对象都有,也仅有一个
monitor。从下图中可以看出,每个 Monitor在某个时刻,只能被一个线程拥有,该线程就是 “Active
Thread”,而其它线程都是 “Waiting Thread”,分别在两个队列 ” Entry Set”和 “Wait
Set”里面等候。在 “Entry Set”中等待的线程状态是 “Waiting for monitor entry”,而在 “Wait
Set”中等待的线程状态是 “in Object.wait()”
总的来说对于Jstack日志 :
- Deadlock:表示有死锁
- Waiting on condition:等待某个资源或条件发生来唤醒自己。具体需要结合jstacktrace来分析,比>如线程正在sleep,网络读写繁忙而等待
- Blocked:阻塞
- Waiting on monitor entry:在等待获取锁
- Java VisualVM : java可视化程序,存在与jdk/bin中 , 可以用来分析dump文件
命令介绍
jps