如何在运行时判断类属于项目代码还是依赖库?
判断Java方法继承来源及父类归属的可行方案
一、识别继承自父类的方法
要区分当前类的方法是自身声明还是继承而来,核心是对比两类方法集合:
- 调用
Class.getDeclaredMethods():获取当前类自己声明的所有方法(包含私有方法,但不含继承的方法) - 调用
Class.getMethods():获取当前类所有可访问的公开方法(包含继承自父类/接口的方法) - 遍历
getMethods()返回的方法,若方法的getDeclaringClass()不是当前类,且不在getDeclaredMethods()的结果中,即可判定该方法继承自父类。 - 可选:如果不需要统计
Object类的通用方法(如toString()、hashCode()),可以额外判断getDeclaringClass()是否为Object.class并排除。
二、区分父类是项目自身还是依赖库
类加载器的思路可行,但需要结合类的代码来源路径判断,而非仅依赖类加载器实例:
1. 通过CodeSource判断类的来源路径
每个类的ProtectionDomain关联了它的代码来源,可通过以下步骤判断:
- 获取父类的
Class对象后,调用clazz.getProtectionDomain().getCodeSource()得到CodeSource实例 - 若
CodeSource不为null,调用getLocation()获取类所在的jar包或目录URL - 项目自身类通常来自编译后的输出目录(如
target/classes、build/classes)或项目自有模块的jar;依赖库类则来自本地仓库(如~/.m2/repository)或第三方jar目录 - 示例代码:
public static boolean isProjectInternalClass(Class<?> clazz) { ProtectionDomain pd = clazz.getProtectionDomain(); if (pd == null) return false; CodeSource cs = pd.getCodeSource(); if (cs == null) return false; String location = cs.getLocation().toString(); // 根据项目实际情况调整匹配规则,比如包含项目编译目录、自有模块jar名 return location.contains("target/classes") || location.contains("build/classes") || location.contains("my-project-module-"); }
2. 适配多模块/多包场景
- 不要单纯依赖包名判断,但可以结合项目根包前缀辅助验证:比如项目所有模块的根包都是
com.mycompany,则先判断父类包名是否以该前缀开头,再结合路径判断,提升准确性 - 多模块项目中,每个模块的编译路径会包含模块名称(如
module-user/target/classes),可将模块名称加入路径匹配规则
3. 特殊场景处理
- 动态生成的类(如代理类、ASM生成类)的
CodeSource可能为null,可直接判定为非项目自身类 - 多模块间的依赖类(如模块A依赖模块B的类)属于项目自身,需将模块B的jar名或编译目录加入匹配规则
内容的提问来源于stack exchange,提问作者Hofi
相关产品推荐
相关产品推荐

