Есть ли способ узнать, была ли Java-программа запущена из командной строки или из jar-файла? - PullRequest
33 голосов
/ 20 мая 2010

Я хочу либо отобразить сообщение в консоли, либо всплывающее окно, поэтому, если параметр не указан, я хочу знать, к какому из них я должен отобразить

Что-то вроде:

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

Ответы [ 7 ]

18 голосов
/ 20 мая 2010

Прямой ответ: вы не можете сказать, как была запущена 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 для Консоль , хотя и не является водонепроницаемым, настоятельно намекает на то, что объект консоли (если он существует) пишет в консоль и не может быть перенаправлен.

Спасибо @Stephen Denne за подсказку !GraphicsEnvironment.isHeadless().

4 голосов
/ 20 мая 2010

Мне неясен вопрос, но я собираюсь его интерпретировать, поскольку вы хотите различать следующие 2

java -jar fred.jar

и

java package.Main

Вот контурная строка программы

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 голосов
/ 20 мая 2010

Трюк System.console(), кажется, делает работу.

Вот альтернатива: в классе есть Class getProtectionDomain () , который может использоваться для определения источника кода и местоположения оттуда.

Забавно, этот метод доступен с 1.2

Я знал, что использовал это раньше, вот оригинальный ответ 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 видео http://img237.imageshack.us/img237/4301/capturadepantalla201005j.png

1 голос
/ 20 мая 2010

Вы можете попробовать:

if (System.console() != null) {
    // Console attached to the JVM: command prompt output
    System.out.println("...");
} else {
    // No console: use Swing
}
0 голосов
/ 21 мая 2010

Вы можете получить все входные аргументы с помощью RuntimeMBean.getInputArguments (), это можно использовать для определения, когда включена отладка.

РЕДАКТИРОВАТЬ: Однако аргумент -jar не один из них. (

0 голосов
/ 20 мая 2010

это правда, что невозможно сказать, как была вызвана JVM. но ... есть способ обойти это. Вы предположили, что когда пользователь дважды щелкнул по JAR, то работает GUI ... Хорошо. так что давайте расширим это предположение. проверьте .. откуда класс был вызван, каталог. проверьте этот каталог .. при условии, что это обычное использование, когда есть файл * .jar, пользователь должен запустить приложение из jar-файла .. но один недостаток заключается в том, что пользователь также может щелкнуть файл основного класса. Хахаха

0 голосов
/ 20 мая 2010

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

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