可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
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");
}
}
回答1:
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.
回答2:
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.
回答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 )
回答4:
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:
From http://java.itags.org/java-essentials/15972/
try {
GraphicsEnvironment.getLocalGraphicsEnvironment();
} catch(Throwable ex) {
System.out.println("No graphical environment is available.");
}
回答6:
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
回答7:
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. :(