我正在尋找一種實用方法,以便給定一個類將返回從外部運行此類所需的完整類路徑。這意味着類所在的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