JVM常用命令参数
1、JPS
JPS全称 Java Process Status Tool,这个命令与Liunx的PS很像,下面我们测试一下这个命令,首先编写一段非常简单的Java代码。
JPS的语法 JPS [options] [hostid]
options:选项
-q: 只显示进程 ID (PID),不显示类名或其他信息。
-l: 显示主类和启动 JAR 文件的完整名称。
-m: 显示传递给 main 方法的参数。
-v: 显示 JVM 启动时的 classpath。
-D: 指定一个系统属性。
-help: 显示帮助信息。
plain
public class JVMTest {
public static void main(String[] args) {
while (true){
//do nothing
}
}
}
使用JPS命令,可以看到我们刚才启动的Java进程,同时进程号为7484
2、JInfo
Jinfo全称:Configuration info of java,java配置信息,可以查看JVM参数和动态的修改部分JVM参数
格式 jinfo [options]
-flag : 查看或设置指定的 JVM 标志。
-sysprops: 显示系统属性。
-flags: 显示 JVM 启动时的所有标志。
-help: 显示帮助信息。
示例:以刚才德尔JVMTest为例,输入命令 jinfo 7484,如下图会打印JVM的相关参数
前面说了,jinfo可以修改部分JVM参数,那么如何查看哪些参数是可以被修改的呢?这里可以使用以下命令
java -XX:+PrintFlagsFinal -version | grep manageable
3、Jstat
jstat:全称 java vitrual Machine statistic monitoring tool,是一个查看Java进程状态的工具,语法格式:
jstat {option} [interval] [vmid] [sleeptime]
参数说明
{option}: 指定要收集的信息类型。
[interval]: 采样间隔时间(毫秒),默认为 0(即只收集一次信息)。
[vmid]: Java 虚拟机的进程 ID。
[sleeptime]: 在多次采样之间暂停的时间(毫秒),仅在 interval 大于 0 时有效。
常见选项
-version: 显示版本信息。
-help: 显示帮助信息。
-gc: 显示垃圾收集统计信息。
-gccapacity: 显示各个内存区域的容量信息。
-class: 显示类加载统计信息。
-compiler: 显示即时编译器统计信息。
-print: 打印详细的统计信息。
-gcutil: 显示垃圾收集利用率信息。
-gccause: 显示导致垃圾收集的原因。
-sys: 显示系统信息。
比如我们想查看刚才的进程的GC情况,可以使用命令 jstat -gc 7484
参数解释:
S0C/S1C: Survivor 区域的容量。
S0U/S1U: Survivor 区域的使用量。
EC: Eden 区域的容量。
EU: Eden 区域的使用量。
OC: Old 区域的容量。
OU: Old 区域的使用量。
MC: Metaspace 的容量。
MU: Metaspace 的使用量。
CCSC: Compressed Class Space 的容量。
CCSU: Compressed Class Space 的使用量。
YGC: Young Generation 的垃圾收集次数。
YGCT: Young Generation 的垃圾收集总时间。
FGC: Full Garbage Collection 的次数。
FGCT: Full Garbage Collection 的总时间。
GCT: 总的垃圾收集时间。
5、jstack
jstack是java栈的跟踪器,可以打印出java应用程序中所有线程的信息、包含堆栈信息、调用栈信息、锁等信息,所以常用于诊断死锁、内存泄漏等等
jstack的命令行格式如下 jstack [-options]
常用参数 -l:打印关于锁的相关信息
示例一:普通进程
还是以刚才的进程为例:jstack 7484
那么如何查看这些信息呢,我们截取一部分内容
这部分内容展示的信息如下:
内容 | 含义 |
---|---|
main | 当前线程名称叫main |
#1 | 线程编号1 |
os_prio=0 | 系统中,当前线程优先级为0 |
cpu=2387656.25ms | cpu已经执行了2387656.25ms |
elapsed=2391.06s | JVM 启动到现在已经过去了大约 2391 秒 |
tid=0x000001661696f860 nid=0x1a64 | tid=0x000001661696f860 表示该线程的内部 ID。 nid=0x1a64 表示该线程的本地线程 ID(通常是操作系统分配的 ID)。 |
runnable | runnable 表示该线程当前处于可运行状态。 |
[0x000000545b1ff000] | [0x000000545b1ff000] 表示该线程的堆栈指针地址。 |
java.lang.Thread.State: RUNNABLE | java.lang.Thread.State: RUNNABLE 再次确认该线程的状态为可运行状态。 |
at net.xdlcass.JVMTest.main(JVMTest.java:6) | at net.xdlcass.JVMTest.main(JVMTest.java:6) 表示该线程当前正在执行 net.xdlcass.JVMTest 类中的 main 方法,具体在第 6 行。 |
Locked ownable synchronizers: - None | None 表示该线程没有锁定任何同步器(如锁或监视器)。 |
示例二:死锁
plain
public class DeadLock {
private final static Object lock1 = new Object();
private final static Object lock2 = new Object();
public static void main(String[] args) {
Thread thread1 = new Thread(() -> {
synchronized (lock2){
try {
System.out.println("thread1 get lock 2");
Thread.sleep(200L);
synchronized (lock1){
System.out.println("thread1 get lock 1");
}
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
});
Thread thread2 = new Thread(() -> {
synchronized (lock1){
try {
Thread.sleep(200L);
System.out.println("thread2 get lock 1");
synchronized (lock2){
System.out.println("thread2 get lock 2");
System.out.println(1111);
}
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
});
thread1.start();
thread2.start();
}
}
我们使用jstack来演示
示例三:CPU过高
首先我们编写一个案例用于让CPU飙高,代码如下
plain
public class HighCPU {
/**
* 提高 CPU 占用的方法。
*/
public static void increaseCPULoad() {
while (true) {
// 进行一些计算操作
int a = 1;
for (int i = 0; i < 100000000; i++) {
a *= 2;
a /= 2;
}
}
}
public static void main(String[] args) {
// 创建多个线程来提高 CPU 占用
int numThreads = Runtime.getRuntime().availableProcessors(); // 根据处理器数量创建线程
System.out.println("Number of available processors: " + numThreads);
Thread[] threads = new Thread[numThreads];
for (int i = 0; i < numThreads; i++) {
threads[i] = new Thread(HighCPU::increaseCPULoad);
threads[i].start();
}
}
}
代码解析:首先根据处理器数量来确定创建的线程数量,然后创建线程不断的死循环执行一些逻辑,这样可以让CPU寻思飙高。一般我们会用top命令来确定是哪个进程,但是现在我们知道是哪个进程所以直接省略这一步。
直接使用命令 jstack
部分内容如下:
未完待续,希望对你有所帮助。