问题描述
我正在尝试制作一个 Java 工具,它将扫描 Java 应用程序的结构并提供一些有意义的信息.为此,我需要能够从项目位置(JAR/WAR 或仅文件夹)扫描所有 .class 文件,并使用反射来了解它们的方法.事实证明,这几乎是不可能的.
I am trying to make a Java tool that will scan the structure of a Java application and provide some meaningful information. To do this, I need to be able to scan all of the .class files from the project location (JAR/WAR or just a folder) and use reflection to read about their methods. This is proving to be near impossible.
我可以找到很多基于 URLClassloader 的解决方案,它们允许我从目录/存档中加载特定的类,但没有一个允许我在没有关于类名或包结构的任何信息的情况下加载类.
I can find a lot of solutions based on URLClassloader that allow me to load specific classes from a directory/archive, but none that will allow me to load classes without having any information about the class name or package structure.
我想我表达得不好.我的问题不是我无法获得所有的类文件,我可以通过递归等来做到这一点并正确定位它们.我的问题是为每个类文件获取一个 Class 对象.
I think I phrased this poorly. My issue is not that I can't get all of the class files, I can do that with recursion etc. and locate them properly. My issue is obtaining a Class object for each class file.
推荐答案
以下代码从 JAR 文件加载所有类.它不需要了解有关类的任何信息.类的名称是从 JarEntry 中提取的.
The following code loads all classes from a JAR file. It does not need to know anything about the classes. The names of the classes are extracted from the JarEntry.
JarFile jarFile = new JarFile(pathToJar);
Enumeration<JarEntry> e = jarFile.entries();
URL[] urls = { new URL("jar:file:" + pathToJar+"!/") };
URLClassLoader cl = URLClassLoader.newInstance(urls);
while (e.hasMoreElements()) {
JarEntry je = e.nextElement();
if(je.isDirectory() || !je.getName().endsWith(".class")){
continue;
}
// -6 because of .class
String className = je.getName().substring(0,je.getName().length()-6);
className = className.replace('/', '.');
Class c = cl.loadClass(className);
}
正如上面评论中所建议的,javassist 也是一种可能性.在while循环之前的某个地方初始化一个ClassPool形成上面的代码,而不是用类加载器加载类,你可以创建一个CtClass对象:
As suggested in the comments above, javassist would also be a possibility.Initialize a ClassPool somewhere before the while loop form the code above, and instead of loading the class with the class loader, you could create a CtClass object:
ClassPool cp = ClassPool.getDefault();
...
CtClass ctClass = cp.get(className);
从 ctClass 中,您可以获取所有方法、字段、嵌套类、....看一下javassist api:https://jboss-javassist.github.io/javassist/html/index.html
From the ctClass, you can get all methods, fields, nested classes, ....Take a look at the javassist api:https://jboss-javassist.github.io/javassist/html/index.html
这篇关于如何在运行时从文件夹或 JAR 加载类?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!