Is there a way to know if a Java program was started from the command line or from a jar file?

前端 未结 7 1974
伪装坚强ぢ
伪装坚强ぢ 2021-02-03 20:45

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:

相关标签:
7条回答
  • 2021-02-03 21:05

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

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

    0 讨论(0)
  • 2021-02-03 21:09

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

    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:

    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.

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

    0 讨论(0)
  • 2021-02-03 21:09

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

    try {
        GraphicsEnvironment.getLocalGraphicsEnvironment();
    } catch(Throwable ex) {
        System.out.println("No graphical environment is available.");
    }
    
    0 讨论(0)
  • 2021-02-03 21:10

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

    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.

    The funny is, this method is available since 1.2

    I knew I used this before, here's the original answer by 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 )

    0 讨论(0)
  • 2021-02-03 21:11

    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

    0 讨论(0)
  • 2021-02-03 21:16

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

    java -jar fred.jar

    and

    java package.Main

    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.

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

    0 讨论(0)
提交回复
热议问题