从 jar 中调用时,ClassLoader 总是 returns null
ClassLoader always returns null when called from within a jar
我 运行 在通过 maven 从我的代码创建 jar 后遇到了库加载问题。我在 Ubuntu 上使用了 intelliJ idea。我将问题分解为这种情况:
从 idea 中调用以下代码,它会正确打印路径。
package com.myproject;
public class Starter {
public static void main(String[] args) {
File classpathRoot = new File(Starter.class.getResource("/").getPath());
System.out.println(classpathRoot.getPath());
}
}
输出为:
/home/ted/java/myproject/target/classes
当我调用 mvn install
并尝试使用以下命令从命令行 运行 它时,我得到一个 NullPointerException
因为 class.getResource()
returns null
:
cd /home/ted/java/myproject/target/
java -cp myproject-0.1-SNAPSHOT.jar com.myproject.Starter
调用相同:
cd /home/ted/java/myproject/target/
java -Djava.library.path=. -cp myproject-0.1-SNAPSHOT.jar com.myproject.Starter
我改用class.getClassLoader().getRessource("")
也没关系。通过 class.getClassLoader().getRessource("file.txt")
.
访问目标目录内的单个文件时出现同样的问题
我想用这种方式加载同一目录中的本机文件(而不是从 jar 内部)。我的方法有什么问题?
JVM 中的class路径加载机制具有高度可扩展性,因此通常很难保证一种方法适用于所有情况。例如在你的 IDE 中起作用的东西在容器中 运行 时可能不起作用,因为你的 IDE 和你的容器可能具有高度专业化的 class 加载程序,具有不同的要求。
您可以采用两层方法。如果上述方法失败,您可以从系统属性中获取 classpath,并扫描它以查找您感兴趣的 jar 文件,然后从该条目中提取目录。
例如
public static void main(String[] args) {
File f = findJarLocation("jaxb-impl.jar");
System.out.println(f);
}
public static File findJarLocation(String entryName) {
String pathSep = System.getProperty("path.separator");
String[] pathEntries = System.getProperty("java.class.path").split(pathSep);
for(String entry : pathEntries) {
File f = new File(entry);
if(f.getName().equals(entryName)) {
return f.getParentFile();
}
}
return null;
}
我 运行 在通过 maven 从我的代码创建 jar 后遇到了库加载问题。我在 Ubuntu 上使用了 intelliJ idea。我将问题分解为这种情况:
从 idea 中调用以下代码,它会正确打印路径。
package com.myproject;
public class Starter {
public static void main(String[] args) {
File classpathRoot = new File(Starter.class.getResource("/").getPath());
System.out.println(classpathRoot.getPath());
}
}
输出为:
/home/ted/java/myproject/target/classes
当我调用 mvn install
并尝试使用以下命令从命令行 运行 它时,我得到一个 NullPointerException
因为 class.getResource()
returns null
:
cd /home/ted/java/myproject/target/
java -cp myproject-0.1-SNAPSHOT.jar com.myproject.Starter
调用相同:
cd /home/ted/java/myproject/target/
java -Djava.library.path=. -cp myproject-0.1-SNAPSHOT.jar com.myproject.Starter
我改用class.getClassLoader().getRessource("")
也没关系。通过 class.getClassLoader().getRessource("file.txt")
.
我想用这种方式加载同一目录中的本机文件(而不是从 jar 内部)。我的方法有什么问题?
JVM 中的class路径加载机制具有高度可扩展性,因此通常很难保证一种方法适用于所有情况。例如在你的 IDE 中起作用的东西在容器中 运行 时可能不起作用,因为你的 IDE 和你的容器可能具有高度专业化的 class 加载程序,具有不同的要求。
您可以采用两层方法。如果上述方法失败,您可以从系统属性中获取 classpath,并扫描它以查找您感兴趣的 jar 文件,然后从该条目中提取目录。
例如
public static void main(String[] args) {
File f = findJarLocation("jaxb-impl.jar");
System.out.println(f);
}
public static File findJarLocation(String entryName) {
String pathSep = System.getProperty("path.separator");
String[] pathEntries = System.getProperty("java.class.path").split(pathSep);
for(String entry : pathEntries) {
File f = new File(entry);
if(f.getName().equals(entryName)) {
return f.getParentFile();
}
}
return null;
}