45

我有一个应用程序,我的一些用户从 Eclipse 运行,而其他用户使用 jar 文件运行它。

我希望在从 jar 中运行时执行一些操作,但我不希望在从 Eclipse 中运行时执行它们。

有没有办法在运行时知道当前应用程序是否从 jar 中运行?

谢谢!

迪克拉

4

8 回答 8

44

好吧,您可以判断一个类是否已从 JAR 文件加载 - 使用Foo.class.getResource("Foo.class")并查看返回的 URL 是否以“jar:”开头

例如,以这个程序为例:

public class Foo {

    public static void main(String[] args) {
        System.out.println(Foo.class.getResource("Foo.class"));
    }
}

运行它从文件系统加载文件:

file:/C:/Users/Jon/Test/com/whatever/Foo.class

从 jar 文件运行它:

jar:file:/C:/Users/Jon/Test/foo.jar!/com/whatever/Foo.class
于 2009-01-27T07:38:39.180 回答
15

我有两个更好的解决方案。第一的:

URL url = this.getClass().getClassLoader().getResource("input.txt");
URLConnection urlConnection = url.openConnection();
if (urlConnection instanceof JarURLConnection) {
    // run in jar
} else {
    // run in ide
}

第二:

String protocol = this.getClass().getResource(this.getClass.getName() + ".class").getProtocol();
if(Objects.equals(protocol, "jar")){
    // run in jar
} else if(Objects.equals(protocol, "file")) {
    // run in ide
}
于 2017-12-09T03:57:10.377 回答
8

您可以检查 Equinox 启动器的系统类路径属性:

if (System.getProperty("java.class.path").contains("org.eclipse.equinox.launcher")) {
    System.out.println("You're running inside Eclipse");
}

您可以检查一些其他潜在属性,您可以在 Eclipse 中通过Help -> About -> Configuration Details.

如果您想知道是从 JAR 运行还是从一堆类文件运行,Jon 的回答很好。但是,如果您在这两种情况下都使用 JAR,那么它不会告诉您您需要什么。

于 2009-01-27T07:51:57.547 回答
6

操作方法

package com.rgagnon;

public class HelloClass {
 public static void main(String[] args) {
    new HelloClass().say();
 }

 public void say() {
   String className = this.getClass().getName().replace('.', '/');
   String classJar =  
     this.getClass().getResource("/" + className + ".class").toString();
   if (classJar.startsWith("jar:")) {
     System.out.println("*** running from jar!");
   }
   System.out.println(classJar);
 }
}

会给:

>jar cvfm Hello.jar manifest.mft com\rgagnon\HelloClass.class
added manifest
adding: com/rgagnon/HelloClass.class (in=1059) (out=601) (deflated 43%)

>java com.rgagnon.HelloClass
file:/C:/DEV/WORK/JAVA/com/rgagnon/HelloClass.class

>java -jar Hello.jar
*** running from jar!
jar:file:/C:/DEV/WORK/JAVA/Hello.jar!/com/rgagnon/HelloClass.class

正如Hosam Aly所指出的,这并不能完全回答这个问题。
我把它留在那里作为一般参考,作为维基答案。

于 2009-01-27T07:46:44.920 回答
6

如果您查询JAR文件名,它将在从JAR文件运行时起作用,否则它将返回类似classes的内容,因此可以使用以下代码:

import java.io.File;

public class JarUtilities
{
    public static String getJarName()
    {
        return new File(JarUtilities.class.getProtectionDomain()
                                .getCodeSource()
                                .getLocation()
                                .getPath())
                       .getName();
    }

    public static boolean runningFromJar()
    {
        return getJarName().contains(".jar");
    }
}

编辑:

如果您需要更高的准确性并抵制重命名文件扩展名,请检查文件是否包含MANIFEST.MF应该工作:

public static boolean runningFromJAR()
{
    try
    {
        String jarFilePath = new File(JarUtilities.class.getProtectionDomain()
                .getCodeSource()
                .getLocation()
                .getPath()).
                toString();
        jarFilePath = URLDecoder.decode(jarFilePath, "UTF-8");

        try (ZipFile zipFile = new ZipFile(jarFilePath))
        {
            ZipEntry zipEntry = zipFile.getEntry("META-INF/MANIFEST.MF");

            return zipEntry != null;
        }
    } catch (Exception exception)
    {
        return false;
    }
}
于 2015-09-24T16:03:13.903 回答
2

这是一些您可以正常运行或作为 jar 运行的代码。

import java.applet.Applet;
import java.net.URL;
import java.security.CodeSource;

public class TestApplet extends Applet {

    public TestApplet(){    
        URL path = TestApplet.class.getResource("TestApplet.class");

        if(path.toString().startsWith("jar:"))
            System.out.println("I'm in a jar");
        else
            System.out.println("I'm not in a jar");
    }

    public static void main(String args[]) throws Exception{
        new TestApplet();
    }
}

要将其放入 jar 中并运行它,请使用以下命令:

jar cf test.jar TestApplet.class
java -cp test.jar TestApplet
于 2012-06-13T02:22:15.847 回答
1

另一种方法是将信息放入清单文件中,并测试该信息在运行时是否可用。

如果是,则代码以“-jar”开头。否则,它会以另一种方式启动,例如直接从 Eclipse 启动。

于 2009-01-27T08:03:29.147 回答
1

你可以试试:

boolean inJar = false;

try
{
  CodeSource cs = DataResolver.class.getProtectionDomain().getCodeSource();
  inJar = cs.getLocation().toURI().getPath().endsWith(".jar");
}
catch (URISyntaxException e)
{
e.printStackTrace();
}

如果您从 jar 文件运行,则 cs.getLocation().toURI() 将为您提供该文件的 URI;如果您从 Eclipse 内部运行,那么它可能是包含您的类文件的目录的路径。

于 2009-01-27T10:25:19.470 回答