![](/img/trans.png)
[英]Maven install error with mule, com.sun.tools.jar not found in jdk
[英]Adding com.sun.tools.jar in classpath of jar
我在使用jdk1.8.0_121/lib/tools.jar
存在的tools.jar
遇到問題。
我的$JAVA_HOME
設置為:
# echo $JAVA_HOME
/usr/local/java/jdk1.8.0_121
tools.jar
的路徑是:
# ls /usr/local/java/jdk1.8.0_121/lib/tools.jar
/usr/local/java/jdk1.8.0_121/lib/tools.jar
我使用以下java
可執行文件來運行代碼:
/usr/local/java/jdk1.8.0_161/bin/java
但是,當我訪問VirtualMachine類時,它會拋出
Caused by: java.lang.ClassNotFoundException: com.sun.tools.attach.VirtualMachine
at java.net.URLClassLoader.findClass(URLClassLoader.java:381) ~[na:1.8.0_161]
at java.lang.ClassLoader.loadClass(ClassLoader.java:424) ~[na:1.8.0_161]
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:338) ~[na:1.8.0_161]
at java.lang.ClassLoader.loadClass(ClassLoader.java:357) ~[na:1.8.0_161]
... 72 common frames omitted
有人可以解釋為什么Java
無法在其類路徑中找到lib/tools.jar
& 我該怎么做才能糾正這種行為?
為了在我的本地機器上運行,我在我的 pom 中添加了以下依賴項:
<dependency>
<groupId>com.sun</groupId>
<artifactId>tools</artifactId>
<version>1.8</version>
<scope>system</scope>
<systemPath>${java.home}/../lib/tools.jar</systemPath>
</dependency>
但是,當我將它部署在服務器上時,由於system
范圍,這個 jar 沒有打包,它也沒有在服務器的 jdk 路徑上找到這個 jar。
不是應該自動找到所有jdk jar嗎?
我還嘗試在 jar 的 MANIFEST 文件的類路徑條目中添加環境變量$JAVA_HOME
,如下所示:
Manifest-Version: 1.0
Archiver-Version: Plexus Archiver
Built-By: pankajsinghal
Class-Path: $JAVA_HOME/lib/
Created-By: Apache Maven 3.5.4
Build-Jdk: 1.8.0_181
但是,這也行不通。 另外,我不想在我的代碼中明確添加這個庫的 jar,因為它是一個 JDK 庫,我猜訪問它的正確方法是從系統的 JDK 路徑本身。 所以,在這個方向本身尋找解決方案。
任何幫助都非常感謝。
您必須在項目屬性中添加該 jar。 在 Eclipse 中,將此 Jar 添加到您的構建路徑右鍵單擊項目 > 構建路徑 > 配置構建路徑 > 選擇庫選項卡 > 單擊添加外部庫 > 選擇 Jar 文件。
你可以這樣試試:
java -cp "/path/your.jar:/usr/local/java/jdk1.8.0_121/lib/tools.jar" your.MainClass
或參考以下內容:
希望對你有幫助。
您可以直接將toos.jar 添加到您當前的classLoader 中,但這只是一個想法。
File getJar = new File(folderLibsPath + File.separator + "tools.jar");
URLClassLoader classLoaderExt = (URLClassLoader) this.getClassLoader();
URL jarUrl = getJar.toURI().toURL();
Method method = URLClassLoader.class.getDeclaredMethod("addURL", URL.class);
method.setAccessible(true);
method.invoke(classLoaderExt, jarUrl);
引用自: 如何在運行時動態加載 JAR 文件?
並且不要忘記加載 attach.so(或 attach.dll)
通過System.load(absPath)
或System.loadLibrary(dllName)
File attachedDLL = new File(folderLibFilePath);
if (attachedDLL.exists()) {
System.load(attachedDLL.getAbsolutePath());
}
我想我們遇到了同樣的問題,這段代碼適用於我的情況。
此外,還有另一種方法可以將 tools.jar 添加到類路徑中,但實際上它們做了同樣的事情:
public void onEnable() throws Exception {
URLClassPath ucp = (URLClassPath) Reflection.getPrivateField("ucp", this.getClassLoader().getParent()); // reflect the subClass of URLClassLoader
File getJar = new File(folderLibsPath + File.separator + "tools.jar");
URL jarUrl = getJar.toURI().toURL();
ucp.addURL(jarUrl); // or just change its "URLs" field by put your jarURL in its Stack
}
但應該提到的是,這種方式 Java 將使用AppClassLoader(SystemClassLoader)
來加載 tools.jar(也是調用程序 - 您的應用程序會)。 如果您使用CustomClassLoader
這可能會對您的原始類初始化產生不良影響。 (因為根據Java 父委托模型, superClassLoader 無法知道其 subClassLoader 加載哪個類)。
因此,如果您正在 customClassLoader(系統類加載器的子類)下開發插件,則應在分離 VM 后刪除 AppClassLoader 中的類路徑(這意味着讓自定義PluginClassLoader
加載它,或者不是它的超級加載器)。
這里我用反射來完成。
public class Main {
public void onEnable() throws Exception {
/** load attach.dll */
System.loadLibrary("attach");
/** load tools.jar */
URLClassPath ucp = (URLClassPath) Reflection.getPrivateField("ucp", this.getClassLoader().getParent());
File getJar = new File(folderLibsPath + File.separator + "tools.jar");
URL jarUrl = getJar.toURI().toURL();
ucp.addURL(jarUrl);
/** attach, load, detach VM */
VirtualMachine vm;
vm = VirtualMachine.attach(this.getPid());
// if the current jar itself is the agent
vm.loadAgent(new File(this.getClass().getProtectionDomain().getCodeSource().getLocation().toURI().getPath()).getAbsolutePath());
vm.detach();
/** change the classLoader back to your custom */
changeClassLoaderBack();
/** unload native DLL Lib */
unloadNativeLibs(); // or you can add a condition to unload attach.dll only
}
public void changeClassLoaderBack() {
URLClassPath ucp = (URLClassPath) Reflection.getPrivateField("ucp", this.getClassLoader().getParent());
/** reset field path */
List<?> path = (ArrayList<?>) Reflection.getPrivateField("path", ucp);
List<URL> newPath = new ArrayList<>();
path.forEach((v) -> {
if(!((URL)v).getPath().contains("toos.jar") && !((URL)v).getPath().contains(this.getPlugin().getName())) {
newPath.add(((URL)v));
}
});
Reflection.setPrivateField("path", ucp, newPath);
/** reset field URLs */
Reflection.setPrivateField("urls", ucp, new Stack<URL>());
/** reset fields loader and LMAP */
List<Object> newLoader = new ArrayList<>();
Map<Object, Object> newLMAP = new HashMap<>();
((HashMap<?,?>)Reflection.getPrivateField("lmap", ucp)).forEach((k,v) -> {
if (!((String)k).contains("tools.jar") && !((String)k).contains(this.getPlugin().getName())) {
newLMAP.put(k, v);
newLoader.add(v);
};
});
Reflection.setPrivateField("lmap", ucp, newLMAP);
Reflection.setPrivateField("loaders", ucp, newLoader);
}
private String getPid() {
RuntimeMXBean bean = ManagementFactory.getRuntimeMXBean();
String pid = bean.getName();
if (pid.contains("@")) {
pid = pid.substring(0, pid.indexOf("@"));
}
return pid;
}
private void unloadNativeLibs(ClassLoader unloadDLLfromWhichLoader) {
try {
ClassLoader classLoader = unloadDLLfromWhichLoader;
Field field = ClassLoader.class.getDeclaredField("nativeLibraries");
field.setAccessible(true);
Vector<?> libs = (Vector<?>) field.get(classLoader);
Iterator<?> it = libs.iterator();
Object o;
while (it.hasNext()) {
o = it.next();
Method finalize = o.getClass().getDeclaredMethod("finalize", new Class[0]);
finalize.setAccessible(true);
finalize.invoke(o, new Object[0]);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
public class Reflection {
public static Object getPrivateField(String fieldName, Object object) {
Field field;
Object o = null;
try {
field = object.getClass().getDeclaredField(fieldName);
field.setAccessible(true);
o = field.get(object);
}
catch (NoSuchFieldException e) {
e.printStackTrace();
}
catch (IllegalAccessException e) {
e.printStackTrace();
}
return o;
}
public static void setPrivateField(String fieldName, Object object, Object newField) {
Field field;
try {
field = object.getClass().getDeclaredField(fieldName);
field.setAccessible(true);
field.set(object, newField);
}
catch (NoSuchFieldException e) {
e.printStackTrace();
}
catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
希望它可以在某些方面幫助你
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.