提问人:Hofi 提问时间:11/13/2023 更新时间:11/13/2023 访问量:41
在运行时检查类是代码的一部分还是依赖项的一部分
Check at runtime whether a class is part of the code or part of one of the dependencies
问:
我正在开发一个引擎,该引擎使用 Java Reflect 库来获取类及其超类的方法。为了进行分析,我需要知道哪些方法是由超类继承的,以及超类是其中一个库的一部分,还是该类是项目本身的一部分。有什么方法可以确定这一点吗?
我尝试使用类加载器,但我要么不知道哪种是正确的方法,要么它不起作用(我宁愿这么认为),因为类加载器也可以加载依赖项的类。
此外,一个项目可能有许多模块和包,这使得(在我的机会下,但也许我错了)无法使用包,该类是其中的一部分。
答:
1赞
queeg
11/13/2023
#1
您需要将问题分为几个不同的步骤:
- 一个类的父类是什么?
- 从哪里加载一些类?
- 源是否从主模块加载了类?
一个类的父类是什么?
在任何实例上,您都可以使用 .getClass() 方法,也可以直接在代码中引用类似 String.class 的内容。
获得类后,运行 getSuperclass() 以查找父类。 请注意,这并不关心实现的接口。
从哪里加载一些类?
在通过遍历继承树获得的每个类上,都可以运行 getClassloader()。根据类加载器本身,您可以获得更多信息。
此外,getPackage() 信息将为您提供有关该类的一些信息。但是,可以将包拆分到不同的 jar 文件和类加载器之间,这使得检测有点棘手。
一个非常强大的解决方案是获取从中加载类的 URL。为此,请向类(或类加载器)询问该类的 URL,如下所示:
Class clazz = ... (some class in question)
URL location = clazz.getResource('/' + clazz.getName().replace('.', '/') + ".class");
有了它,您将收到类似
jar:file:/jdk/jre/lib/rt.jar!/java/lang/Object.class
源是否从主模块加载了类?
现在这一切都归结为比较 URL 字符串。只需查看感叹号之前的部分,您应该有一个 jar 文件。答案现在应该很容易了。
评论
2赞
Holger
11/13/2023
对于顶级类,可以简化为 .但是从 Java 9 开始,et al 的结果将是这样的。clazz.getResource('/' + clazz.getName().replace('.', '/') + ".class")
clazz.getResource(clazz.getSimpleName() + ".class")
Object.class
jrt:/java.base/java/lang/Object.class
0赞
queeg
11/14/2023
嗯。这可能意味着我们必须区分 Java9+ 或模块化应用程序。那里的 URL 是否仍然具有可比性?请随时更新我的答案。
评论