Java 以编程方式分析jar文件
我需要以编程方式计算给定jar文件中已编译类、接口和枚举的数量(因此我需要三个单独的数字)。哪种API可以帮助我?(我不能使用第三方库。)Java 以编程方式分析jar文件,java,jar,classloader,Java,Jar,Classloader,我需要以编程方式计算给定jar文件中已编译类、接口和枚举的数量(因此我需要三个单独的数字)。哪种API可以帮助我?(我不能使用第三方库。) 我已经尝试过相当棘手的方案,似乎并不总是正确的。也就是说,我将每个ZipEntry读入一个字节[],然后将结果提供给我的自定义类加载器,该类加载器扩展了标准的CalssLoader,只将这个字节[]发送给ClassLoader.defineClass(它是受保护的,不能直接从应用程序代码中调用)。完整代码是。jar文件是具有特定模式的zip文件。 您可以使用
我已经尝试过相当棘手的方案,似乎并不总是正确的。也就是说,我将每个ZipEntry读入一个字节[],然后将结果提供给我的自定义类加载器,该类加载器扩展了标准的CalssLoader,只将这个字节[]发送给ClassLoader.defineClass(它是受保护的,不能直接从应用程序代码中调用)。完整代码是。jar文件是具有特定模式的zip文件。 您可以使用ZipFile和ZipEntry或它们的子类JarFile和JarEntry 这段代码(自定义类加载器的方法)将返回一个映射,其中包含您需要的每种类型的“类”的数组
public Map<String, List<Class<?>>> loadAndScanJar(File jarFile)
throws ClassNotFoundException, ZipException, IOException {
// Load the jar file into the JVM
// You can remove this if the jar file already loaded.
super.addURL(jarFile.toURI().toURL());
Map<String, List<Class<?>>> classes = new HashMap<String, List<Class<?>>>();
List<Class<?>> interfaces = new ArrayList<Class<?>>();
List<Class<?>> clazzes = new ArrayList<Class<?>>();
List<Class<?>> enums = new ArrayList<Class<?>>();
List<Class<?>> annotations = new ArrayList<Class<?>>();
classes.put("interfaces", interfaces);
classes.put("classes", clazzes);
classes.put("annotations", annotations);
classes.put("enums", enums);
// Count the classes loaded
int count = 0;
// Your jar file
JarFile jar = new JarFile(jarFile);
// Getting the files into the jar
Enumeration<? extends JarEntry> enumeration = jar.entries();
// Iterates into the files in the jar file
while (enumeration.hasMoreElements()) {
ZipEntry zipEntry = enumeration.nextElement();
// Is this a class?
if (zipEntry.getName().endsWith(".class")) {
// Relative path of file into the jar.
String className = zipEntry.getName();
// Complete class name
className = className.replace(".class", "").replace("/", ".");
// Load class definition from JVM
Class<?> clazz = this.loadClass(className);
try {
// Verify the type of the "class"
if (clazz.isInterface()) {
interfaces.add(clazz);
} else if (clazz.isAnnotation()) {
annotations.add(clazz);
} else if (clazz.isEnum()) {
enums.add(clazz);
} else {
clazzes.add(clazz);
}
count++;
} catch (ClassCastException e) {
}
}
}
System.out.println("Total: " + count);
return classes;
}
public-Map>>classes=new-HashMap>interfaces=new-ArrayList>clazzes=new-ArrayList>enums=new-ArrayList>annotations=new-ArrayList-clazz=this.loadClass(className);
试一试{
//验证“类”的类型
if(clazz.isInterface()){
接口。添加(clazz);
}else if(clazz.isAnnotation()){
添加注释(clazz);
}else if(clazz.isEnum()){
enums.add(clazz);
}否则{
添加(clazz);
}
计数++;
}catch(ClassCastException e){
}
}
}
系统输出打印项次(“总计:+计数);
返回类;
}
你能调用ZipEntry.getName()
看看它是不是一个.class
文件吗?或者您需要单独计算类和接口(以及枚举?)吗?我需要单独计算它们(另外,我们知道并非所有的.class文件都包含正确的字节码)。我们不希望计算具有错误字节码的.class文件。在这种情况下,在这种情况下,您现有的方法看起来不错-但在什么情况下它不能正常工作?我在Apache commons-io.jar(直接链接:)上尝试了它。那里有76个.class文件,但我的代码输出47 2 0(类接口枚举)。非常感谢,它工作得几乎完美。一些小细节:为了能够使用super.addURL
,您应该扩展URLClassLoader
,而不仅仅是ClassLoader
。然后,您必须定义构造函数,该构造函数使用URL数组调用super
。我希望我能给它输入null,但得到了一个异常。所以我用一个URL构建了一个数组,它对应于我的jar。。。这个很好用。。。很抱歉,对超类的误解,这是一个UrlClassloader。。。