有没有办法知道Java程序是从命令行还是从jar文件启动的?

时间:2021-03-21 00:10:53

I want to either display a message in the console or a pop up, so in case a parameter is not specified, I want to know to which should I display

我想要在控制台中显示一条消息或弹出,所以如果没有指定参数,我想知道我应该显示哪个

Something like:

就像是:

if( !file.exists() ) {
    if( fromCommandLine()){
        System.out.println("File doesn't exists");
    }else if ( fromDoubleClickOnJar() ) {
        JOptionPane.showMessage(null, "File doesn't exists");
    }
 }

7 个解决方案

#1


17  

The straight forward answer is that you cannot tell how the JVM was launched.

直截了当的答案是,您无法分辨JVM是如何启动的。

But for the example use-case in your question, you don't really need to know how the JVM was launched. What you really need to know is whether the user will see a message written to the console. And the way to do that would be something like this:

但是对于您的问题中的示例用例,您并不需要知道JVM是如何启动的。您真正需要知道的是用户是否会看到写入控制台的消息。这样做的方法是这样的:

if (!file.exists()) {
    Console console = System.console();
    if (console != null) {
        console.format("File doesn't exists%n");
    } else if (!GraphicsEnvironment.isHeadless()) {
        JOptionPane.showMessage(null, "File doesn't exists");
    } else {
        // Put it in the log
    }
 }

The javadoc for Console, while not water tight, strongly hints that a Console object (if it exists) writes to a console and cannot be redirected.

控制台的javadoc虽然不防水,但强烈暗示Console对象(如果存在)写入控制台并且无法重定向。

Thanks @Stephen Denne for the !GraphicsEnvironment.isHeadless() tip.

感谢@Stephen Denne的!GraphicsEnvironment.isHeadless()提示。

#2


4  

I'm not clear on the question but I'm going to interpret it as you want to differentiate between the following 2

我不清楚这个问题,但我会解释它,因为你想要区分以下2

java -jar fred.jar

java -jar fred.jar

and

java package.Main

java包。主

Here is an outline line of the program

这是该程序的概述

import sun.jvmstat.monitor.*;
...
HostIdentifier hostId = new HostIdentifier("localhost");
MonitoredHost monitoredHost = MonitoredHost.getMonitoredHost(hostId);
Set jvms = monitoredHost.activeVms();
for (Object i: jvms) {
   VmIdentifier id = new VmIdentifier("//" + i + "?mode=r");
   MonitoredVm vm = monitoredHost.getMonitoredVm(id, 0);   
   System.out.println(i);
   System.out.println("\t main class: " + MonitoredVmUtil.mainClass(vm, false));
   System.out.println("\t main args: " + MonitoredVmUtil.mainArgs(vm));
   System.out.println("\t jvmArgs: " + MonitoredVmUtil.jvmArgs(vm));
   monitoredHost.detach(vm);
}

The call MonitoredVmUtil.mainClass(vm, false) will either return 'jar' or the name of your main class eg Main.

调用MonitoredVmUtil.mainClass(vm,false)将返回'jar'或主类的名称,例如Main。

You have to use $JAVA_HOME/lib/tools.jar to compile and run.

您必须使用$ JAVA_HOME / lib / tools.jar进行编译和运行。

#3


2  

The System.console() trick seems to do the work.

System.console()技巧似乎可以完成这项工作。

Here's an alternative: there's a method in the class Class getProtectionDomain() which may be used to know the source of the code the the location from there.

这里有一个替代方法:类getProtectionDomain()中有一个方法,它可以用来从那里知道代码的来源。

The funny is, this method is available since 1.2

有趣的是,这种方法从1.2开始就可用

I knew I used this before, here's the original answer by erickson

我知道我以前用过这个,这是erickson的原始答案

Here's the proof of concept:

这是概念证明:

public class FromJar {
    public static void main( String [] args ) {
        if ( FromJar.class
                 .getProtectionDomain()
                 .getCodeSource()
                 .getLocation()
                 .getFile()
                 .endsWith(".jar") ) {

            javax.swing.JOptionPane.showMessageDialog( null, "Launched from Jar" );

       } else {
            System.out.println("Launched NOT from Jar :P ");
       }
    }
}

Here's a short ( 1m aprox ) video to see this code running ( and being written with cat :-o )

这是一个短的(1m aprox)视频,看这个代码正在运行(并用cat编写:-o)

Youtube video http://img237.imageshack.us/img237/4301/capturadepantalla201005j.png

Youtube视频http://img237.imageshack.us/img237/4301/capturadepantalla201005j.png

#4


1  

You can try with:

您可以尝试:

if (System.console() != null) {
    // Console attached to the JVM: command prompt output
    System.out.println("...");
} else {
    // No console: use Swing
}

#5


0  

From http://java.itags.org/java-essentials/15972/

来自http://java.itags.org/java-essentials/15972/

try {
    GraphicsEnvironment.getLocalGraphicsEnvironment();
} catch(Throwable ex) {
    System.out.println("No graphical environment is available.");
}

#6


0  

it's true that it is impossible to tell how the JVM was invoked. but... there's a way to side step this. you assumed that when the user double clicked on a JAR, then there's GUI running... ok. so let's extend this assumption. check.. from where the class was invoked, the directory. check that directory.. assuming it's a normal usage, when there's a *.jar file, then the user must've started the app from a jar.. but one flaw is that the user can also click on the main class file. hahahaha

确实无法告诉JVM是如何被调用的。但是......有一种方法可以支持这一步。你假设当用户双击JAR时,那么GUI正在运行......好吧。所以让我们扩展这个假设。检查..从调用类的位置,目录。检查该目录..假设它是正常用法,当有* .jar文件时,那么用户必须从jar启动应用程序..但是一个缺陷是用户也可以单击主类文件。哈哈哈哈

#7


0  

You can get all the input arguments with RuntimeMBean.getInputArguments(), this can be used to detect when debugging is enabled.

您可以使用RuntimeMBean.getInputArguments()获取所有输入参数,这可用于检测何时启用调试。

EDIT: However, the -jar argument isn't one of them. :(

编辑:但是,-jar参数不是其中之一。 :(

#1


17  

The straight forward answer is that you cannot tell how the JVM was launched.

直截了当的答案是,您无法分辨JVM是如何启动的。

But for the example use-case in your question, you don't really need to know how the JVM was launched. What you really need to know is whether the user will see a message written to the console. And the way to do that would be something like this:

但是对于您的问题中的示例用例,您并不需要知道JVM是如何启动的。您真正需要知道的是用户是否会看到写入控制台的消息。这样做的方法是这样的:

if (!file.exists()) {
    Console console = System.console();
    if (console != null) {
        console.format("File doesn't exists%n");
    } else if (!GraphicsEnvironment.isHeadless()) {
        JOptionPane.showMessage(null, "File doesn't exists");
    } else {
        // Put it in the log
    }
 }

The javadoc for Console, while not water tight, strongly hints that a Console object (if it exists) writes to a console and cannot be redirected.

控制台的javadoc虽然不防水,但强烈暗示Console对象(如果存在)写入控制台并且无法重定向。

Thanks @Stephen Denne for the !GraphicsEnvironment.isHeadless() tip.

感谢@Stephen Denne的!GraphicsEnvironment.isHeadless()提示。

#2


4  

I'm not clear on the question but I'm going to interpret it as you want to differentiate between the following 2

我不清楚这个问题,但我会解释它,因为你想要区分以下2

java -jar fred.jar

java -jar fred.jar

and

java package.Main

java包。主

Here is an outline line of the program

这是该程序的概述

import sun.jvmstat.monitor.*;
...
HostIdentifier hostId = new HostIdentifier("localhost");
MonitoredHost monitoredHost = MonitoredHost.getMonitoredHost(hostId);
Set jvms = monitoredHost.activeVms();
for (Object i: jvms) {
   VmIdentifier id = new VmIdentifier("//" + i + "?mode=r");
   MonitoredVm vm = monitoredHost.getMonitoredVm(id, 0);   
   System.out.println(i);
   System.out.println("\t main class: " + MonitoredVmUtil.mainClass(vm, false));
   System.out.println("\t main args: " + MonitoredVmUtil.mainArgs(vm));
   System.out.println("\t jvmArgs: " + MonitoredVmUtil.jvmArgs(vm));
   monitoredHost.detach(vm);
}

The call MonitoredVmUtil.mainClass(vm, false) will either return 'jar' or the name of your main class eg Main.

调用MonitoredVmUtil.mainClass(vm,false)将返回'jar'或主类的名称,例如Main。

You have to use $JAVA_HOME/lib/tools.jar to compile and run.

您必须使用$ JAVA_HOME / lib / tools.jar进行编译和运行。

#3


2  

The System.console() trick seems to do the work.

System.console()技巧似乎可以完成这项工作。

Here's an alternative: there's a method in the class Class getProtectionDomain() which may be used to know the source of the code the the location from there.

这里有一个替代方法:类getProtectionDomain()中有一个方法,它可以用来从那里知道代码的来源。

The funny is, this method is available since 1.2

有趣的是,这种方法从1.2开始就可用

I knew I used this before, here's the original answer by erickson

我知道我以前用过这个,这是erickson的原始答案

Here's the proof of concept:

这是概念证明:

public class FromJar {
    public static void main( String [] args ) {
        if ( FromJar.class
                 .getProtectionDomain()
                 .getCodeSource()
                 .getLocation()
                 .getFile()
                 .endsWith(".jar") ) {

            javax.swing.JOptionPane.showMessageDialog( null, "Launched from Jar" );

       } else {
            System.out.println("Launched NOT from Jar :P ");
       }
    }
}

Here's a short ( 1m aprox ) video to see this code running ( and being written with cat :-o )

这是一个短的(1m aprox)视频,看这个代码正在运行(并用cat编写:-o)

Youtube video http://img237.imageshack.us/img237/4301/capturadepantalla201005j.png

Youtube视频http://img237.imageshack.us/img237/4301/capturadepantalla201005j.png

#4


1  

You can try with:

您可以尝试:

if (System.console() != null) {
    // Console attached to the JVM: command prompt output
    System.out.println("...");
} else {
    // No console: use Swing
}

#5


0  

From http://java.itags.org/java-essentials/15972/

来自http://java.itags.org/java-essentials/15972/

try {
    GraphicsEnvironment.getLocalGraphicsEnvironment();
} catch(Throwable ex) {
    System.out.println("No graphical environment is available.");
}

#6


0  

it's true that it is impossible to tell how the JVM was invoked. but... there's a way to side step this. you assumed that when the user double clicked on a JAR, then there's GUI running... ok. so let's extend this assumption. check.. from where the class was invoked, the directory. check that directory.. assuming it's a normal usage, when there's a *.jar file, then the user must've started the app from a jar.. but one flaw is that the user can also click on the main class file. hahahaha

确实无法告诉JVM是如何被调用的。但是......有一种方法可以支持这一步。你假设当用户双击JAR时,那么GUI正在运行......好吧。所以让我们扩展这个假设。检查..从调用类的位置,目录。检查该目录..假设它是正常用法,当有* .jar文件时,那么用户必须从jar启动应用程序..但是一个缺陷是用户也可以单击主类文件。哈哈哈哈

#7


0  

You can get all the input arguments with RuntimeMBean.getInputArguments(), this can be used to detect when debugging is enabled.

您可以使用RuntimeMBean.getInputArguments()获取所有输入参数,这可用于检测何时启用调试。

EDIT: However, the -jar argument isn't one of them. :(

编辑:但是,-jar参数不是其中之一。 :(