我们基于Java的服务器应用程序报告了异常高的类加载器时间:
# jstat -class 10625 1000
Loaded Bytes Unloaded Bytes Time
4781 9165.6 114 185.2 17769.35
4781 9165.6 114 185.2 17769.85
4781 9165.6 114 185.2 17770.36
4781 9165.6 114 185.2 17771.11
4781 9165.6 114 185.2 17771.73
这是在一台运行了大约8个小时的服务器上。jstat报告称,它已经花了17769秒(~4h56m!)来加载类,每秒大约多出0.5-0.6秒!我们一直在跟踪一个性能问题,这是我们寻找罪魁祸首的最佳人选。可以肯定的是,我们检查了其他Java服务:jstat在Time
列中显示了一个非常低的值(几秒钟,甚至在运行了几个小时之后)
我们的代码不进行持续的类加载,但我们不能排除一个行为不端的第三方库。我们启用了-verbose:gc
,希望能诊断出问题。但是,一旦我们的服务器加载了所有的类(在一分钟左右的繁忙流量内),详细的类日志就变得安静了——我们有点期待看到给定jstat数据的一系列活动。
我的问题是:
- 这真的说明有问题吗
- 如果是这样,还可以做些什么来诊断它
如果有任何建议,我将不胜感激。
这似乎是一个真正的问题。假设类加载时间增加,而加载类的数量保持不变,我可以得出结论,应用程序试图一次又一次地加载丢失的类,例如通过Class.forName
或ClassLoader.loadClass
。
如果缺少一个类,JVM将在抛出ClassNotFoundException
之前扫描整个类路径。如果类路径包含许多JAR甚至网络URL,那么这可能会花费大量时间。
为了进一步诊断,我建议使用Class.forName
和ClassLoader.loadClass
方法或截取ClassNotFoundExceptions
。