代码之家  ›  专栏  ›  技术社区  ›  OscarRyz

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

  •  33
  • OscarRyz  · 技术社区  · 14 年前

    我想在控制台中显示一条消息或弹出窗口,因此如果没有指定参数,我想知道应该显示到哪一个。

    类似:

    if( !file.exists() ) {
        if( fromCommandLine()){
            System.out.println("File doesn't exists");
        }else if ( fromDoubleClickOnJar() ) {
            JOptionPane.showMessage(null, "File doesn't exists");
        }
     }
    
    7 回复  |  直到 8 年前
        1
  •  18
  •   stmoebius    12 年前

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

    但是对于您的问题中的示例用例,您实际上不需要知道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
        }
     }
    

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

    感谢@stephen denne !GraphicsEnvironment.isHeadless() 小费。

        2
  •  4
  •   Chuk Lee    14 年前

    我对这个问题不太清楚,但我会把它解释为你想区分以下两个方面

    Java-Jar Fr.jar

    主程序包

    这是节目的大纲

    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);
    }
    

    呼叫 MonitoredVmUtil.mainClass(vm, false) 将返回' jar '或您的主要类的名称,例如 Main .

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

        3
  •  3
  •   Community holdenweb    7 年前

    这个 System.console() 诡计似乎起作用了。

    还有一种选择:类中有一个方法 Class getProtectionDomain() 它可以用来知道代码的来源以及从那里的位置。

    有趣的是,这种方法从1.2开始就有了。

    我知道我以前用过这个,这是 original answer 通过 erickson

    这是概念证明:

    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 ");
           }
        }
    }
    

    这是一个简短的(大约1米)视频,可以看到这段代码的运行(和编写 cat :-O)

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

        4
  •  1
  •   schastar    14 年前

    您可以尝试:

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

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

    try {
        GraphicsEnvironment.getLocalGraphicsEnvironment();
    } catch(Throwable ex) {
        System.out.println("No graphical environment is available.");
    }
    
        6
  •  0
  •   p01ntbl4nk    14 年前

    确实,不可能知道如何调用JVM。 但是…有一种方法可以绕过这个。 您假设当用户双击一个jar时,有一个gui正在运行… 好啊。那么让我们扩展这个假设。 检查…从调用类的位置调用目录。 检查那个目录.. 假设这是一个正常的用法,当有一个*.jar文件时,那么用户一定是从jar启动了应用程序。 但是一个缺陷是用户也可以点击主类文件。 哈哈哈哈

        7
  •  0
  •   Peter Lawrey    14 年前

    可以使用runtimeMBean.getInputArguments()获取所有输入参数,这可用于在启用调试时进行检测。

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