我正在使用一些第三方代碼,當給定'-classpath'命令行參數時不會設置java.class.path,而只是創建一個類加載器,將命令行中指定類路徑的所有項目的URL添加到類加載器,然後將其設置爲上下文類加載器。 在我編寫的代碼的插件類中,我得到了這個類加載器的一個實例,並且以某種方式需要使用它來獲取底層類路徑,以便我可以在調用JavaCompiler.getTask(.. 。)並編譯一些其他代碼。 然而,似乎無論如何都不能從ClassLoader獲取ClassPath,並且因爲java.class.path未設置,我似乎無法訪問應用程序最初被調用的基礎類路徑...任何想法?如何從classloader獲取classpath?
回答
如果類加載器使用URL,則它必須是URLClassloader
。您可以訪問的是其中定義類路徑與其父母ClassLoader
並列的URL。
要獲得的URL,只要做到以下幾點:
((URLClassLoader) (Thread.currentThread().getContextClassLoader())).getURLs()
以供將來參考,如果您需要在類路徑傳遞給ProcessBuilder
:
StringBuffer buffer = new StringBuffer();
for (URL url :
((URLClassLoader) (Thread.currentThread()
.getContextClassLoader())).getURLs()) {
buffer.append(new File(url.getPath()));
buffer.append(System.getProperty("path.separator"));
}
String classpath = buffer.toString();
int toIndex = classpath
.lastIndexOf(System.getProperty("path.separator"));
classpath = classpath.substring(0, toIndex);
ProcessBuilder builder = new ProcessBuilder("java",
"-classpath", classpath, "com.a.b.c.TestProgram");
如果其他的答案唐沒有工作,試試這個:
ClassLoader cl = ClassLoader.getSystemClassLoader();
URL[] urls = ((URLClassLoader) cl).getURLs();
for (URL url: urls) {
System.out.println(url.getFile());
}
其他答案在大多數情況下是正確的,但它在某些設置中變得更復雜:例如Maven,Tomcat和JUnit有它們自己的類路徑支持,它們不使用系統類路徑。
到目前爲止,這是最完整的系統,我已成功地拿出了(此代碼是從我Fast Classpath Scanner項目):
/** The unique elements of the classpath, as an ordered list. */
private final ArrayList<File> classpathElements = new ArrayList<>();
/** The unique elements of the classpath, as a set. */
private final HashSet<String> classpathElementsSet = new HashSet<>();
/** Clear the classpath. */
private void clearClasspath() {
classpathElements.clear();
classpathElementsSet.clear();
}
/** Add a classpath element. */
private void addClasspathElement(String pathElement) {
if (classpathElementsSet.add(pathElement)) {
final File file = new File(pathElement);
if (file.exists()) {
classpathElements.add(file);
}
}
}
/** Parse the system classpath. */
private void parseSystemClasspath() {
// Look for all unique classloaders.
// Keep them in an order that (hopefully) reflects the order in which class resolution occurs.
ArrayList<ClassLoader> classLoaders = new ArrayList<>();
HashSet<ClassLoader> classLoadersSet = new HashSet<>();
classLoadersSet.add(ClassLoader.getSystemClassLoader());
classLoaders.add(ClassLoader.getSystemClassLoader());
if (classLoadersSet.add(Thread.currentThread().getContextClassLoader())) {
classLoaders.add(Thread.currentThread().getContextClassLoader());
}
// Dirty method for looking for any other classloaders on the call stack
try {
// Generate stacktrace
throw new Exception();
} catch (Exception e) {
StackTraceElement[] stacktrace = e.getStackTrace();
for (StackTraceElement elt : stacktrace) {
try {
ClassLoader cl = Class.forName(elt.getClassName()).getClassLoader();
if (classLoadersSet.add(cl)) {
classLoaders.add(cl);
}
} catch (ClassNotFoundException e1) {
}
}
}
// Get file paths for URLs of each classloader.
clearClasspath();
for (ClassLoader cl : classLoaders) {
if (cl != null) {
for (URL url : ((URLClassLoader) cl).getURLs()) {
if ("file".equals(url.getProtocol())) {
addClasspathElement(url.getFile());
}
}
}
}
}
/** Override the system classpath with a custom classpath to search. */
public FastClasspathScanner overrideClasspath(String classpath) {
clearClasspath();
for (String pathElement : classpath.split(File.pathSeparator)) {
addClasspathElement(pathElement);
}
return this;
}
/**
* Get a list of unique elements on the classpath (directories and files) as File objects, preserving order.
* Classpath elements that do not exist are not included in the list.
*/
public ArrayList<File> getUniqueClasspathElements() {
return classpathElements;
}
絕對是最完整的答案,並積極發展,如果你關注這個項目。 – 2015-08-21 10:34:56
在調用堆棧中查找任何其他類加載器的髒方法正是我所需要的!非常感謝! – FelipeKunzler 2016-02-19 19:27:48
@ luke-hutchison你的圖書館是一個拯救生命的人!對於任何想要爲各種運行時環境獲取類路徑的解決方案的人來說,這都是最好的選擇。 – Dan 2016-02-26 02:49:15
刪除此代碼到一個空的JSP頁面來查看ClassLoader的層次和相關裝在每個級別的罐子。
訪問()以下方法也可以單獨使用
<%!
public void visit(StringBuilder sb, int indent, ClassLoader classLoader) {
if (indent > 20 || classLoader == null)
return;
String indentStr = new String(new char[indent]).replace("\0", " ");
sb.append("\n");
sb.append(indentStr);
sb.append(classLoader.getClass().getName());
sb.append(":");
if (classLoader instanceof java.net.URLClassLoader) {
java.net.URL[] urls = ((java.net.URLClassLoader)classLoader).getURLs();
for (java.net.URL url : urls) {
sb.append("\n");
sb.append(indentStr);
sb.append(url);
}
}
sb.append("\n");
visit(sb, indent + 1, classLoader.getParent());
}
%>
<%
StringBuilder sb = new StringBuilder();
visit(sb,1,this.getClass().getClassLoader());
%>
<pre>
<%=sb%>
</pre>
- 1. 從Gradle org.gradle.api.Project獲取ClassLoader?
- 2. 如何從classpath獲取jar文件?
- 3. 在ant build.xml中從環境獲取CLASSPATH
- 4. 使用ClassLoader獲取資源的路徑
- 5. Java的定製ClassLoader獲取資源
- 6. 如何獲取netbeans的classLoader指定項目
- 7. 如何從類型變量中獲取ClassLoader(用於使用泛型來分類)
- 8. 如何關閉ClassLoader?
- 9. 如何從classLoader獲得java.lang;類而不是編譯文件* .java
- 10. 從引導斜槓的ClassLoader獲取資源
- 11. 從jar中獲取資源:classloader vs class resourceasstream
- 12. 如何在classpath
- 13. Perl Inline :: Java。如何在編譯時獲取Classpath環境變量?
- 14. 從Python中獲取.bat文件中構建的CLASSPATH
- 15. 如何從classpath中ANT TestNG的ECLIPSE
- 16. IKVM從哪裏獲得它的CLASSPATH?
- 17. 如何縮短classpath?
- 18. 如何在JBoss 6中分離ear classloader和system classloader?
- 19. ISelection - 我如何在導航器中爲選定的類獲取ClassLoader
- 20. 閱讀從classpath中
- 21. 加載從classpath中
- 22. 如何使Groovy從您的ClassLoader而不是文件系統讀取類?
- 23. 如何設置Spring的Classpath
- 24. 的ClassLoader:
- 25. Classloader Filtering
- 26. Java classloader
- 27. 從Android加載圖像文件從ClassLoader
- 28. 如何從os.popen()獲取stderr?
- 29. 如何從ArrayList.subList獲取ArrayList?
- 30. 如何從indexPathsForSelectedRows獲取「行」?
的工作,謝謝:) – 2012-07-23 16:28:48
不客氣! – 2012-07-23 16:36:47