获取每个库加载的 java 类 的计数

Get count of java classes loaded per library

在第 33-34 页的关于 Lambda 性能的 AWS re:invent presentation(强烈推荐)中,作者使用以下命令列出了每个库中加载的 classes 的计数:

java -cp my.jar -verbose:class Handler | grep '\[Loaded' | grep '.jar\]' | sed -r 's/\[Loaded \([^A-Z]*\)[$A-Za-z0-9]*from.*\]//g' | sort | uniq -c | sort

这基本上提取了命名空间,但不包括第一个大写字母,即 class 名称。输出应该看起来像这样:

143 com.fasterxml.jackson
219 org.apache.http
373 com.google
507 com.amazonaws

然而,这仅适用于 Java 8 class 加载程序日志,其具有以下格式(此示例应输出 java.io):

[Loaded java.io.Serializable from shared objects file]

从 Java 9+ 开始的 class 加载程序日志具有这种不同的格式:

[0.041s][info][class,load] java.io.Serializable source: jrt:/java.base

sed 命令需要如何更新才能产生与上面相同的输出?

我试过以下方法,但整行都是在正则表达式组中提取的,而不仅仅是 class 库。我也在 Mac 上 运行,所以我不得不添加一个 -r 标志并删除一些转义字符:

java -cp my.jar -verbose:class Handler | grep '[class,load]' | grep '.jar' | sed -r 's/.*\[class,load\] ([^A-Z]*)[$A-Za-z0-9]*source.*//g'

由于记录有字段 space 分隔,我们可以利用 cut 获取所需的字段,然后使用 sed 提取包子字符串。 ([a-z.]+)\.[A-Z].* 正则表达式查找小写字母和点,直到第一个点后跟大写字母。

echo "[0.041s][info][class,load] java.io.Serializable source: jrt:/java.base" | cut -d ' ' -f2 | sed -E 's/([a-z.]+)\.[A-Z].*//g'

结果:

java.io

如果首选 sed 解决方案,此命令也将执行 grepcut 作业:

echo "[0.041s]..." | sed -nE '/class,load/ s/[^ ]+ ([^ ]+)// ; s/([a-z.]+)\.[A-Z].*//p'

grep : /class,load/
切:s/[^ ]+ ([^ ]+)//
摘录:s/([a-z.]+)\.[A-Z].*//p