我有一个应用程序,有些用户从Eclipse运行,其他用户则使用jar文件运行。
我想要在从jar文件中运行时执行某些操作,但不希望在从Eclipse运行时执行这些操作。
是否有一种方法可以在运行时知道当前应用程序是否从jar文件中运行?
谢谢!
Dikla
我有一个应用程序,有些用户从Eclipse运行,其他用户则使用jar文件运行。
我想要在从jar文件中运行时执行某些操作,但不希望在从Eclipse运行时执行这些操作。
是否有一种方法可以在运行时知道当前应用程序是否从jar文件中运行?
谢谢!
Dikla
你可以通过使用Foo.class.getResource("Foo.class")
并查看返回的URL是否以"jar:"开头来判断一个类是否从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
if (resourcePath.startsWith("jar:") || resourcePath.startsWith("rsrc:"))
。 - Starwarswiifoo.class.getName() + ".class"
而不是硬编码类名。 - MasterHD我有两个更好的解决方案。第一个:
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
}
URLConnection
是非常浪费资源的,因此并不比简单地检查协议更好。 - Christopher Schultzthis.getClass().getResource("")
会返回 null 吗?应该改为 this.getClass().getResource(this.getClass.getName() + ".class")
吗? - zhenguoli如果你查询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;
}
}
您可以检查Equinox启动器的系统类路径属性:
if (System.getProperty("java.class.path").contains("org.eclipse.equinox.launcher")) {
System.out.println("You're running inside Eclipse");
}
还有一些其他可能的属性可以检查,您可以通过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);
}
}
Will give:
>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
以下是您可以从普通模式或作为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 cf test.jar TestApplet.class
java -cp test.jar TestApplet
你可以尝试:
boolean inJar = false;
try
{
CodeSource cs = DataResolver.class.getProtectionDomain().getCodeSource();
inJar = cs.getLocation().toURI().getPath().endsWith(".jar");
}
catch (URISyntaxException e)
{
e.printStackTrace();
}