JVM的 jconsole
远程连接
在 JVM 的启动参数上加:
-Djava.rmi.server.hostname=localhost
-Dcom.sun.management.jmxremote
-Dcom.sun.management.jmxremote.port=12345
-Dcom.sun.management.jmxremote.ssl=false
-Dcom.sun.management.jmxremote.authenticate=false
hostname 是 远程目标的ip地址或者域名
port 只是一个开放的端口,别被其他应用使用就行
参数说明
内存
堆内存:内存的增长趋势、垃圾回收的频繁性和耗时情况
非堆内存:平稳性
线程
线程数:过多的线程在上下文切换时的开销
死锁:检测死锁,定位死锁
类
加载的类:JVM通过类加载器将类加载到内存中,类加载是在程序运行期间动态进行的,一个类只会被加载一次
卸载的类:服务关闭时,被加载到内存中的类,应该要被卸载
CPU
是Java程序在运行时,JVM进程所使用的CPU时间与总CPU时间的比例。
在正常的程序运行过程中,CPU占用率可能会在不同的百分比之间波动。
如果CPU占用率持续保持在一个高位,可能的原因:频繁的IO读写操作、线程过多、死锁等。
检测死锁
使用jconsole 来查看线程的状态和活动。如果发生死锁,通常会有一些线程处于 BLOCKED 或 WAITING 状态,且这些状态可能持续很长时间。通过查看线程的堆栈跟踪信息,你可以尝试理解为什么线程被阻塞,并可能找到导致死锁的代码路径。
一旦你识别了死锁的原因,处理死锁通常需要你手动修改代码。这可能包括重新设计数据结构、改进同步策略、避免嵌套锁等。在某些情况下,你可能需要使用更高级的并发控制工具或技术,如 java.util.concurrent 包中的类或者锁分离等策略。
嵌套锁
当一个线程已经持有某个对象的锁时,它再次尝试获取同一个对象的锁。
Java的内建锁(即 synchronized关键字)是隐式支持重入的,即同一个线程可以多次获得同一个对象的锁而不会导致死锁
public class NestedLockingExample {
private final Object lock = new Object();
public void outerMethod() {
synchronized (lock) {
// 持有lock对象的锁
innerMethod();
// 释放lock对象的锁,当outerMethod方法执行完毕后
}
}
public void innerMethod() {
synchronized (lock) {
// 再次持有lock对象的锁(嵌套锁)
// 执行一些需要同步的操作
}
}
public static void main(String[] args) {
NestedLockingExample example = new NestedLockingExample();
example.outerMethod(); // 调用outerMethod,它会调用innerMethod,形成嵌套锁
}
}
废话短说