如何获取正在运行的Java程序的路径

100

有没有一种方法可以获取正在运行的Java程序的主类路径。

结构如下:

D:/
|---Project
       |------bin
       |------src

我想获取路径为D:\Project\bin\

我尝试过System.getProperty("java.class.path");,但问题是,如果我像这样运行

java -classpath D:\Project\bin;D:\Project\src\  Main

Output 
Getting : D:\Project\bin;D:\Project\src\
Want    : D:\Project\bin

有没有什么方法可以做到这一点?



===== 编辑 =====

在这里找到了解决方案

解决方案1(由Jon Skeet提供)

package foo;

public class Test
{
    public static void main(String[] args)
    {
        ClassLoader loader = Test.class.getClassLoader();
        System.out.println(loader.getResource("foo/Test.class"));
    }
}

这将打印出:

file:/C:/Users/Jon/Test/foo/Test.class


解决方案2(由Erickson提供)

URL main = Main.class.getResource("Main.class");
if (!"file".equalsIgnoreCase(main.getProtocol()))
  throw new IllegalStateException("Main class is not stored in a file.");
File path = new File(main.getPath());

请注意,大多数类文件都被组装成JAR文件,因此这种方法不适用于所有情况(因此会出现IllegalStateException)。但是,您可以使用此技术找到包含该类的JAR文件,并通过将getResource()调用替换为getResourceAsStream()调用来获取类文件的内容,这样无论类是在文件系统中还是在JAR文件中都可以工作。


你可以对结果进行标记化处理(围绕着分号“;”切割条目)。 classpath 属性通常包含多个条目(例如,你正在使用的库等)。 也许你应该重新考虑你的需求。如果你只关心一个文件夹,你确定解析 classpath 是个好主意吗? - Matthias
2
@Matthias 请注意,不同平台的路径分隔符是不同的。最好使用 System.getProperty("path.separator"); - Uwe Plonus
1
https://dev59.com/jHRA5IYBdhLWcg3w8SeJ#778246 - Vignesh Vino
像这类问题一样,为什么?你要实现哪个具体的应用程序功能?设置的序列化、自我卸载器等吗? - Andrew Thompson
实际上,该代码正在使用目录中的一些文件。这些文件是什么?它们用于什么?它们是只读还是可读写的? - Andrew Thompson
显示剩余3条评论
4个回答

142

14
说实话,我不认为这个回答能解决问题。系统属性'java.class.path'返回整个类路径,包括JAR文件和所有内容。发帖者正在询问运行主类(工作目录)的路径。 - monzonj
1
工作目录不一定是类文件运行的位置。OP给出的示例证明了这一点。虽然这个答案包括了项目组件的所有位置,但他展示了如何将它们分成各个元素。 - Larry
8
我同意你的看法。在我回答这个问题之后,问题进行了调整,因此我的回答不再匹配。但是,与此同时,很多人发现我的回答很有用,因为它符合标题。这就是为什么我仍然保留它而不删除它的原因。 - René Link

108

尝试使用这段代码:

final File f = new File(MyClass.class.getProtectionDomain().getCodeSource().getLocation().getPath());

用您包含主方法的类替换 'MyClass'。

或者,您也可以使用

System.getProperty("java.class.path")

上述系统属性提供了查找包含类文件的目录和JAR存档文件的路径。类路径的元素由path.separator属性中指定的特定于平台的字符分隔。


在我的jvm(jetty)中,getCodeSource()返回null。 - Daniil Iaitskov
MyClass.class.getProtectionDomain().getCodeSource().getLocation().getPath() 不就足够了吗?为什么要创建一个 File 对象呢? - Mohammad Faisal

27

实际上您并不需要获取到您的主类路径。根据您的例子,您想要获取当前工作目录,也就是您的程序启动的目录。在这种情况下,您可以简单地使用以下代码来获取:

new File(".").getAbsolutePath()

5
从所有答案中,这是最准确的答案。 - monzonj

3
    ClassLoader cl = ClassLoader.getSystemClassLoader();

    URL[] urls = ((URLClassLoader)cl).getURLs();

    for(URL url: urls){
        System.out.println(url.getFile());
    }

1
这通常只会给出您的应用程序启动的路径,这不一定是您的主类所在的位置。 - Matthias
4
系统类加载器也不保证是 URLClassLoader 哦 :P - Qix - MONICA WAS MISTREATED
这对我很有用。谢谢。 - xbmono
5
类转换异常:类jdk.internal.loader.ClassLoaders$AppClassLoader无法强制转换为类java.net.URLClassLoader。 - cdalxndr

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接