背景
-
java
命令的一些选项可以帮助我们观察加载的类的名称, -
jstat
命令的-class
选项可以显示加载的类的数量。
结合这两点,我们就可以着手写个小程序,来观察加载的类的数量的变化过程。
思路
- 既然要观察数量变化的过程,那么我们希望在加载类时有明显的停顿(否则变化太快,太难观察)。
我们可以借助java.util.Scanner
类的nextLine()
方法,来让程序进行等待。 - 既然是观察变化,那么我们希望能多观察几次,所以可以写个
for
循环来加载若干个类
代码
假设当前目录名为 load_test
我们需要创建
Main.java
-
generate.sh
这两个文件。其中Main.java
用于加载一些类,这些类是通过generate.sh
文件生成的。
两个文件的具体内容如下
Main.java
import java.util.Scanner;
public class Main {
public static void main(String[] args) throws Exception {
int cnt = 10;
if (args.length > 0) {
cnt = Integer.parseInt(args[1]);
}
Scanner scanner = new Scanner(System.in);
for (int i = 1; i <= cnt;i++) {
scanner.nextLine();
Class.forName("temp.C" + i);
}
// 为了便于观察,不让程序自动结束
while (true);
}
}
generate.sh
#!/bin/bash
# 如果名为 "temp" 的目录不存在, 则创建它
# 如果名为 "temp" 的目录已经存在, 则删除这个目录下的文件
dir_name="temp"
if [ ! -d "${dir_name}" ];
then
mkdir ${dir_name}
else
rm ${dir_name}/*
fi
# cnt 的默认值是 10, 可以被命令行参数替代
cnt="10"
if [ "$#" -gt 0 ];
then
cnt=${1}
fi
for i in $(seq 1 ${cnt})
do
echo "package ${dir_name};" > "${dir_name}/C${i}.java"
echo "public class C${i} {}" >> "${dir_name}/C${i}.java"
done
javac ${dir_name}/*.java
测试
比如我们想观察5
个类的加载情况,那么可以这样操作
- 在命令行窗口(简称为窗口
A
)中执行./generate.sh 5
命令
生成5个 java 文件
- 在窗口
A
中执行javac Main.java
命令
编译 Main.java
- 在窗口
A
中执行java -verbose:class -XX:+TraceClassLoading -cp . Main 5
命令
运行 Main 类
- 另开一个命令行窗口(简称为窗口
B
),执行jps -l
命令,并在输出中找到和Main
对应的那一行(下图中用红框标出来了)
找到对应的进程id
-
在窗口
B
中执行jstat -class 21844 500
命令(注意21844
需要替换为和Main
对应的进程id,500
表示每隔500ms
输出一次)
观察加载的类的数量
我运行时,看到的效果是571
,说明此时已经加载了571
个类 -
在窗口
A
中随便输入一行内容(最省事的办法就是直接敲回车键),然后就会看到有新的类被加载了(红框里是新加载的类,其中temp.C1
这个类是由generate.sh
生成的)
有两个类刚刚被加载
-
在窗口
B
中观察,会看到加载的类的数量确实增加了2
在窗口B进行确认
-
在窗口
A
中继续输入内容,然后在窗口B
中观察
继续加载其他类
generate.sh
一共创建了 5
个类,在上图可以看到,这 5
个类都被加载了。在窗口 B
中可以看到加载的类的数量最终变成了 577

- 由于
Main.java
中的代码不会自动结束,所以需要在窗口A
中用Ctrl+C
来终止对应的进程。
补充说明
- 关于
jstat
命令的-class
选项的介绍可以参考 https://docs.oracle.com/javase/7/docs/technotes/tools/share/jstat.html#class_option - 在窗口
A
执行命令时,只使用-verbose:class
选项或者-XX:+TraceClassLoading
选项似乎就能看到同样的效果。关于这两个选项的介绍可以参考 https://docs.oracle.com/javase/8/docs/technotes/tools/windows/java.html 一文
网友评论