[Java] 观察加载的类的数量的变化

背景

  • java 命令的一些选项可以帮助我们观察加载的类的名称,
  • jstat 命令的 -class 选项可以显示加载的类的数量。
    结合这两点,我们就可以着手写个小程序,来观察加载的类的数量的变化过程。

思路

  1. 既然要观察数量变化的过程,那么我们希望在加载类时有明显的停顿(否则变化太快,太难观察)。
    我们可以借助 java.util.Scanner 类的 nextLine() 方法,来让程序进行等待。
  2. 既然是观察变化,那么我们希望能多观察几次,所以可以写个 for 循环来加载若干个类

代码

假设当前目录名为 load_test
我们需要创建

  1. Main.java
  2. 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个类的加载情况,那么可以这样操作

  1. 在命令行窗口(简称为窗口 A )中执行 ./generate.sh 5 命令
    生成5个 java 文件
  2. 在窗口 A 中执行 javac Main.java 命令
    编译 Main.java
  3. 在窗口 A 中执行 java -verbose:class -XX:+TraceClassLoading -cp . Main 5 命令
    运行 Main 类
  4. 另开一个命令行窗口(简称为窗口 B ),执行 jps -l 命令,并在输出中找到和 Main 对应的那一行(下图中用红框标出来了)
    找到对应的进程id
  1. 在窗口 B 中执行jstat -class 21844 500命令(注意21844需要替换为和 Main 对应的进程id, 500表示每隔 500ms 输出一次)

    观察加载的类的数量

    我运行时,看到的效果是 571,说明此时已经加载了 571 个类

  2. 在窗口 A 中随便输入一行内容(最省事的办法就是直接敲回车键),然后就会看到有新的类被加载了(红框里是新加载的类,其中 temp.C1 这个类是由 generate.sh 生成的)

    有两个类刚刚被加载

  1. 在窗口 B 中观察,会看到加载的类的数量确实增加了2

    在窗口B进行确认

  2. 在窗口 A 中继续输入内容,然后在窗口 B 中观察

    继续加载其他类

generate.sh 一共创建了 5 个类,在上图可以看到,这 5 个类都被加载了。在窗口 B 中可以看到加载的类的数量最终变成了 577

在窗口B进行确认

  1. 由于 Main.java 中的代码不会自动结束,所以需要在窗口 A 中用 Ctrl+C 来终止对应的进程。

补充说明

  1. 关于 jstat 命令的 -class 选项的介绍可以参考 https://docs.oracle.com/javase/7/docs/technotes/tools/share/jstat.html#class_option
  2. 在窗口 A 执行命令时,只使用 -verbose:class 选项或者 -XX:+TraceClassLoading 选项似乎就能看到同样的效果。关于这两个选项的介绍可以参考 https://docs.oracle.com/javase/8/docs/technotes/tools/windows/java.html 一文
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 用两张图告诉你,为什么你的 App 会卡顿? - Android - 掘金 Cover 有什么料? 从这篇文章中你...
    hw1212阅读 12,949评论 2 59
  • 一.类加载机制 把描述类数据的Class文件(二进制流,来源文件、jar、网络、计算生成proxy)加载到内存,并...
    半数的年阅读 204评论 0 0
  • 什么是类加载器 负责加载class文件,class文件在文件开头由特定的文件标识,将class文件字节码内容加载到...
    尹楷楷阅读 233评论 0 1
  • swift进阶 学习大纲[https://www.jianshu.com/p/0fc67b373540] 上一节,...
    markhetao阅读 718评论 0 0
  • 久违的晴天,家长会。 家长大会开好到教室时,离放学已经没多少时间了。班主任说已经安排了三个家长分享经验。 放学铃声...
    飘雪儿5阅读 7,567评论 16 22