我正在寻找一种实用方法,以便给定一个类将返回从外部运行此类所需的完整类路径。这意味着类所在的jar以及它使用的类的所有jar(或文件夹)。从类获取完整的类路径
更新:有工具可以分析.class文件以查找依赖关系。这不是我要找的。我正在寻找在已经加载的类上使用Java反射API的东西。我会解决一些分析字节码的问题,如果它递归地通过类加载器找到的类,则可以使用
我正在寻找一种实用方法,以便给定一个类将返回从外部运行此类所需的完整类路径。这意味着类所在的jar以及它使用的类的所有jar(或文件夹)。从类获取完整的类路径
更新:有工具可以分析.class文件以查找依赖关系。这不是我要找的。我正在寻找在已经加载的类上使用Java反射API的东西。我会解决一些分析字节码的问题,如果它递归地通过类加载器找到的类,则可以使用
反射不会帮你很多这个。您将需要分析字节码以查找依赖关系。
更新:
好吧。我正在使用多年前创建的库,可以下载here。
下面的代码:
package classdep;
import java.io.InputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import org.jedo.classfile.ClassFile;
import org.jedo.classfile.ConstantPool;
public class Main {
public static void main(String[] args) {
try {
ClassLoader cl = Thread.currentThread().getContextClassLoader();
List<String> classes = new ArrayList<String>();
classes.add(args[0].replace('.', '/'));
for (int i = 0; i < classes.size(); ++i) {
String className = classes.get(i);
URL url = cl.getResource(className + ".class");
if (url == null) {
System.out.println("--- class not found " + className);
} else {
System.out.println(url);
ClassFile classFile = new ClassFile();
InputStream in = url.openStream();
try {
classFile.load(in);
} finally {
in.close();
}
ConstantPool cp = classFile.getConstantPool();
for (String name: cp.getClassNames()) {
if (!classes.contains(name)) {
classes.add(name);
}
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
会给你一个类的所有依赖。应用于org.jedo.classfile时。ClassFile,它会产生以下输出:
file:/D:/projects/casagrande/jedo/build/classes/org/jedo/classfile/ClassFile.class
file:/D:/projects/casagrande/jedo/build/classes/org/jedo/classfile/ConstantPool.class
file:/D:/projects/casagrande/jedo/build/classes/org/jedo/classfile/FieldInfo.class
file:/D:/projects/casagrande/jedo/build/classes/org/jedo/classfile/MethodInfo.class
file:/D:/projects/casagrande/jedo/build/classes/org/jedo/classfile/AttributeInfo.class
jar:file:/C:/Program%20Files/Java/jdk1.6.0_18/jre/lib/rt.jar!/java/io/File.class
jar:file:/C:/Program%20Files/Java/jdk1.6.0_18/jre/lib/rt.jar!/java/io/FileInputStream.class
jar:file:/C:/Program%20Files/Java/jdk1.6.0_18/jre/lib/rt.jar!/java/io/DataInputStream.class
jar:file:/C:/Program%20Files/Java/jdk1.6.0_18/jre/lib/rt.jar!/java/io/StreamCorruptedException.class
jar:file:/C:/Program%20Files/Java/jdk1.6.0_18/jre/lib/rt.jar!/java/io/FileOutputStream.class
jar:file:/C:/Program%20Files/Java/jdk1.6.0_18/jre/lib/rt.jar!/java/io/DataOutputStream.class
jar:file:/C:/Program%20Files/Java/jdk1.6.0_18/jre/lib/rt.jar!/java/lang/StringBuilder.class
jar:file:/C:/Program%20Files/Java/jdk1.6.0_18/jre/lib/rt.jar!/java/lang/StringBuffer.class
jar:file:/C:/Program%20Files/Java/jdk1.6.0_18/jre/lib/rt.jar!/java/lang/Object.class
jar:file:/C:/Program%20Files/Java/jdk1.6.0_18/jre/lib/rt.jar!/java/io/IOException.class
...
后面跟着很多系统类。您需要过滤掉系统类,并解析其他URL以提取.jar文件(如果它是jar)或url(如果它是文件:url)。
有些情况下,在使用类之前无法确定此类。
这并不总是可知的。例如,一个类可以在运行时动态创建,然后加载自定义的ClassLoader
。
我不相信Java存储此信息。
因为我想在外部运行它,让我们假设我知道所有的依赖项都是从实际的文件/ jar中检索的。 – IttayD 2010-08-09 05:22:22
我不认为这是可能的。当然,反射API不支持它。
你可以找到一个类加载器,但你不能找出:
Class.forName()
加载了哪些内容。其实,这有点夸大的事情:
但这一切都非常复杂,我认为它在某些情况下是不可靠的。
clazz.getResource(“/”+ clazz.getName()。replace(“。”,“/”)+“.class”)将返回从中加载文件的文件。删除以后的一切!会给罐子。 – IttayD 2010-08-09 05:24:21
@IttayD - 我不相信这适用于所有类加载器。 – 2010-08-09 05:39:58
我会解决一些分析字节码的问题,如果它递归地通过类加载器找到的类 – IttayD 2010-08-09 05:59:47