如何查找JVM中java.lang.Throwable的所有子类?含未加载类及替代方案
问题描述
我需要为每个错误分配错误码,因此需查找JVM中java.lang.Throwable的所有子类(包括已加载和未加载的类),是否存在其他解决方案?
我曾参考Stack Overflow上的相关问题《How do you find all subclasses of a given class in Java?》,尝试过ClassGraph和org.reflections:reflections:0.10.2工具,但无法找到JDK中java.lang包下的类(如java.lang.NullPointerException)。
使用ClassGraph的代码如下:
ClassGraph classGraph = new ClassGraph() ; ScanResult result = classGraph.enableAllInfo().whitelistPackages( "java.lang" ).scan() ; result.getAllClasses().forEach( c -> System.out.println(c) ) ;
解决方案
1. 修正ClassGraph扫描配置
ClassGraph默认不扫描JDK核心类库,手动开启相关配置后就能捕获java.lang下的异常类:
ClassGraph classGraph = new ClassGraph() .enableAllInfo() .whitelistPackages("java.lang") .scanJarsInJre() // 开启JRE核心Jar包扫描 .ignoreClassVisibility(); // 跳过类访问权限检查 ScanResult result = classGraph.scan(); // 过滤出所有Throwable的子类 result.getAllClasses().stream() .filter(clazz -> clazz.extendsSuperclass("java.lang.Throwable")) .forEach(c -> System.out.println(c.getClassName()));
2. 直接解析JDK核心类文件
绕开扫描工具的限制,自己读取JRE中rt.jar(模块化JDK对应java.base模块)的类文件,用ASM或Javassist等字节码工具分析继承关系:
- 核心步骤:
- 通过
System.getProperty("java.home")获取JRE目录,定位核心类库位置 - 遍历Jar包内所有
.class文件 - 用
ClassReader读取类的父类信息,判断是否继承自Throwable
- 通过
3. 借助JVM Instrumentation API
编写Java Agent并在JVM启动时挂载,既能获取已加载类,也能加载未加载类进行扫描:
// Agent示例代码 public class ThrowableScannerAgent { public static void premain(String agentArgs, Instrumentation inst) { // 遍历所有已加载的类 for (Class<?> clazz : inst.getAllLoadedClasses()) { if (Throwable.class.isAssignableFrom(clazz)) { System.out.println(clazz.getName()); } } // 如需扫描未加载类,可将核心Jar添加到引导类加载器后遍历 } }
该方法需打包Agent并在JVM启动时添加-javaagent参数,步骤稍繁琐但覆盖范围完整。
4. 使用预定义标准异常清单
如果仅需覆盖JDK自带的标准异常类,直接从JDK文档整理一份清单即可,比如:
- Error子类:
OutOfMemoryError、StackOverflowError、NoClassDefFoundError - Exception子类:
NullPointerException、IllegalArgumentException、IOException
这种方式简单直接,适合无需覆盖自定义异常的场景。
内容的提问来源于stack exchange,提问作者Bourbon_7
相关产品推荐
相关产品推荐

