从库 jar 中获取执行位置
get the execution location from within a library jar
我有一个名为 Utils
的 class,它有一个应该确定执行位置的静态方法。
public class Utils {
public static Path getExecutionLocation() throws URISyntaxException {
return Paths.get(Utils.class.getProtectionDomain().getCodeSource().getLocation().toURI());
}
}
在 Eclipse 中,这给了我:C:\Users\USERNAME\workspace\PROJECT\bin\main\
运行 作为一个罐子,这给了我:C:\PATH\TO\JAR\thatJar.jar
两者都正确且符合预期。
现在我在一个名为 someLib.jar
的库中有了 Utils
class。
当我在另一个项目中使用该库时,如果我为该项目构建一个内部包含 someLib.jar
的 jar,它就可以工作。
但在 Eclipse 中,它 return 是通往 someLib.jar
.
的路径
我要return项目执行目录的路径:
C:\Users\USERNAME\workspace\A_PROJECT_USING_SOMELIB\bin\main\
我试过了
return new File(ClassLoader.getSystemClassLoader().getResource(".").getPath()).toPath();
但是在 jar 中失败了,因为 getResource(".")
导致 null
。
我可以从项目内部给 getExecutionLocation
一个 class 作为参数并在其上执行 getProtectionDomain()
。但是我想在这里问问有没有人知道更好的解决办法。
试试这个:
public class Utils {
public static Path getExecutionLocation(Class c) throws URISyntaxException {
return Paths.get(c.getProtectionDomain().getCodeSource().getLocation().toURI());
}
}
所以你将 class 作为参数传递给函数。例如:
public class Main
{
public static void main(String[] args)
{
Utils.getExecutionLocation(Main.class);
}
}
请注意,可能有更直接的解决方案,
但这是我第一个想到的,我想,为什么不呢:)
我找到了一个基于 ClassLoader.getSystemClassLoader()
方法的解决方案,该方法为我提供了 class 加载程序,该加载程序负责使用 someLib.jar.[=14 的项目的主要入口点=]
在 IDE 中,我可以使用 getResource(".")
获取所有资源(和来源)的根路径 URL。
从 jar 文件这不起作用。所以我使用 getResource("META-INF")
获取 META-INF 文件夹(里面有清单)的 URL 并且应该始终存在于 jar 文件中。
也许还不是最优的。但到目前为止我可以使用它。
public static Path getExecutionLocation() throws URISyntaxException, IOException {
// System ClassLoader is on the highest level and responsible for the main entry point
ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
// get the resources root path (works within IDEs)
URL executionLocation = systemClassLoader.getResource(".");
// fallback for jars
if(executionLocation == null) {
// look for META-INF folder
URL metaInfLocation = systemClassLoader.getResource("META-INF");
// URL looks like "jar:file:/C:/path/to/jar/jarfile.jar!/META-INF"
// openConnection on URL - does not really establish connection but checks if URL would be valid
JarURLConnection connection = (JarURLConnection) metaInfLocation.openConnection();
// extracts URL to jar file
executionLocation = connection.getJarFileURL();
}
// impossible to determine
if(executionLocation == null) throw new RuntimeException("Impossible to determine exeution location");
return Paths.get(executionLocation.toURI());
}
我有一个名为 Utils
的 class,它有一个应该确定执行位置的静态方法。
public class Utils {
public static Path getExecutionLocation() throws URISyntaxException {
return Paths.get(Utils.class.getProtectionDomain().getCodeSource().getLocation().toURI());
}
}
在 Eclipse 中,这给了我:C:\Users\USERNAME\workspace\PROJECT\bin\main\
运行 作为一个罐子,这给了我:C:\PATH\TO\JAR\thatJar.jar
两者都正确且符合预期。
现在我在一个名为 someLib.jar
的库中有了 Utils
class。
当我在另一个项目中使用该库时,如果我为该项目构建一个内部包含 someLib.jar
的 jar,它就可以工作。
但在 Eclipse 中,它 return 是通往 someLib.jar
.
我要return项目执行目录的路径:
C:\Users\USERNAME\workspace\A_PROJECT_USING_SOMELIB\bin\main\
我试过了
return new File(ClassLoader.getSystemClassLoader().getResource(".").getPath()).toPath();
但是在 jar 中失败了,因为 getResource(".")
导致 null
。
我可以从项目内部给 getExecutionLocation
一个 class 作为参数并在其上执行 getProtectionDomain()
。但是我想在这里问问有没有人知道更好的解决办法。
试试这个:
public class Utils {
public static Path getExecutionLocation(Class c) throws URISyntaxException {
return Paths.get(c.getProtectionDomain().getCodeSource().getLocation().toURI());
}
}
所以你将 class 作为参数传递给函数。例如:
public class Main
{
public static void main(String[] args)
{
Utils.getExecutionLocation(Main.class);
}
}
请注意,可能有更直接的解决方案, 但这是我第一个想到的,我想,为什么不呢:)
我找到了一个基于 ClassLoader.getSystemClassLoader()
方法的解决方案,该方法为我提供了 class 加载程序,该加载程序负责使用 someLib.jar.[=14 的项目的主要入口点=]
在 IDE 中,我可以使用 getResource(".")
获取所有资源(和来源)的根路径 URL。
从 jar 文件这不起作用。所以我使用 getResource("META-INF")
获取 META-INF 文件夹(里面有清单)的 URL 并且应该始终存在于 jar 文件中。
也许还不是最优的。但到目前为止我可以使用它。
public static Path getExecutionLocation() throws URISyntaxException, IOException {
// System ClassLoader is on the highest level and responsible for the main entry point
ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
// get the resources root path (works within IDEs)
URL executionLocation = systemClassLoader.getResource(".");
// fallback for jars
if(executionLocation == null) {
// look for META-INF folder
URL metaInfLocation = systemClassLoader.getResource("META-INF");
// URL looks like "jar:file:/C:/path/to/jar/jarfile.jar!/META-INF"
// openConnection on URL - does not really establish connection but checks if URL would be valid
JarURLConnection connection = (JarURLConnection) metaInfLocation.openConnection();
// extracts URL to jar file
executionLocation = connection.getJarFileURL();
}
// impossible to determine
if(executionLocation == null) throw new RuntimeException("Impossible to determine exeution location");
return Paths.get(executionLocation.toURI());
}