33

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");
    }
 }
Peter Lang
  • 54,264
  • 27
  • 148
  • 161
OscarRyz
  • 196,001
  • 113
  • 385
  • 569
  • 1
    If you start it from the command line does the application run without a GUI? – Jonathan Holloway May 20 '10 at 00:26
  • Interesting question (+1), but very tricky. Sorry for the deleted answer, I realized that this isn't reliable. I will do some tests. – BalusC May 20 '10 at 00:33
  • @Jon It runs with a GUI in both cases. – OscarRyz May 20 '10 at 00:40
  • @BalusC indeed. The fact you can run the jar from the cmd line makes it worst, but I think there must be a way to know where the class was loaded from, but I don't remember how it was. – OscarRyz May 20 '10 at 00:41
  • 1
    Similar question to http://stackoverflow.com/questions/2469047/can-i-find-out-if-the-java-program-was-launched-using-java-or-javaw – Stephen Denne May 20 '10 at 01:05

7 Answers7

18

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.

stmoebius
  • 662
  • 11
  • 30
Stephen C
  • 698,415
  • 94
  • 811
  • 1,216
  • 2
    `GraphicsEnvironment.isHeadless()` only checks a property (useful as a kind of "please don't try" setting). You'd also want to catch `HeadlessException` in case the property wasn't set, but there is no display (or keyboard or mouse) available. – Stephen Denne May 20 '10 at 02:45
4

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.

Chuk Lee
  • 3,570
  • 22
  • 19
3

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 )

Youtube video

Glorfindel
  • 21,988
  • 13
  • 81
  • 109
OscarRyz
  • 196,001
  • 113
  • 385
  • 569
  • 1
    What would you want to show for `java -cp fromjar.jar FromJar` – Stephen Denne May 20 '10 at 10:43
  • Eh, your question was thus: "How to differentiate if the class was launched as Java Application (as standalone class without `-jar` argument) or as JAR file? (with `-jar` argument)" ? Your initial question namely didn't imply that. I understood that it were JAR files in both cases. Else checking would indeed be very easy... – BalusC May 20 '10 at 15:11
  • @BalusC, yeap, actually what I need is to know if the user doubleclicked on a jar or if it started from the console. I think the `System.console()` answer is the correct. – OscarRyz May 20 '10 at 17:01
2

You can try with:

if (System.console() != null) {
    // Console attached to the JVM: command prompt output
    System.out.println("...");
} else {
    // No console: use Swing
}
schastar
  • 236
  • 2
  • 3
  • this is incorrect. System.console() can return a non-null value, but System.out may still be redirected. (In fact, I can think of two scenarios ...) – Stephen C May 20 '10 at 01:08
0

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

try {
    GraphicsEnvironment.getLocalGraphicsEnvironment();
} catch(Throwable ex) {
    System.out.println("No graphical environment is available.");
}
Sijin
  • 4,530
  • 21
  • 22
  • 1
    Nice one, tested it, but this never throws. I think this is more useful to test if there's any graphics device (headless or not). – BalusC May 20 '10 at 00:57
  • 3
    If I open my console an run a java program, the graphics environment will be there still. – OscarRyz May 20 '10 at 01:29
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

p01ntbl4nk
  • 50
  • 1
  • 9
0

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. :(

Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130