你能告诉运行时你是否在jar中运行java?

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

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

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

谢谢!

Dikla

好吧,您可以判断是否已从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 

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

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

您可以检查其他一些可能的属性,您可以通过“ Help -> About -> Configuration Details在Eclipse中找到这些属性。

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

从方法到

 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所指出的,这并没有完全回答这个问题。
作为维基回答,我把它留在那里作为一般参考。

以下是一些可以从正常或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 

如果查询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(ProgramDirectoryUtilities.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; } } 

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

 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("").getProtocol(); if(Objects.equals(protocol, "jar")){ // run in jar } else if(Objects.equals(protocol, "file")) { // run in ide } 

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

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

你可以尝试:

 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内部运行那么它可能是包含你的类文件的目录的路径。