I know that I can get the command-line arguments in the "main" method, but I need to be able to get them indirectly.
Thanks for your help.
Following expression is exactly what you want:
System.getProperty("sun.java.command")
You can list the threads, find the main thread, and crawl down the stack trace until you find the call to main, and pull out the args.
update a comment points out that this won't work all by itself, and I think the comment is correct. I misremembered the capabilities of stack introspection or mentally mixed in JVMTI.
So, here's plan B. Connect to yourself with JMX. The VM Summary MBean has the args.
Connection name:
pid: 77090 com.basistech.jdd.JDDLauncher -config src/main/config/benson-laptop-config.xml
All this having been said, what you should do is call System.getProperty and live with the need to use -D to pass parameters from the outside world down into your cave.
You could write a wrapper to take the cli and re-format it to use -DPROP=VAL
int main(int argc, char*argv[])
{
std::vector<std::string> in (argv+1,argv+argc), out();
out.push_back("java.exe");
out.push_back("-cp");
out.push_back("my-jar.jar");
out.push_back("main.class")
for( auto it = in.begin(); it!=in.end(); ++in)
{
//process CLI args. turn "-abc","BLAH" into "-Darg.a=true","-Darg.b=true","-Darg.c=BLAH" and push to out
//Do additional processing. Maybe evn use get_opt() or Boost.ProgramOptions
}
//use exec or CreateProcess to launch java with the proper args
//or even use something like WinRun4J's methods to load the jvm.dll
//Then your program shows up as "MyExe.exe" instead of "java.exe"
//Use System.getProperty("arg.a","false") to get the value of a
}
Of course, you could always just tell you users to invoke a bash/batch script with the proper -DA=true type arguments
Related
I'm new with JCommander and I'm trying to use it in my JAVA Command Line Application.
Fisrt thing I did is I've created my CommandLineArguments class.
Now, I'm trying to print options given with arguments in command line. But I think I'm missing something.
Here is my main class :
public static void main(String[] args) {
String[] argv={"-h","host"};
CommandLineArguments arguments=new CommandLineArguments();
JCommander commands= new JCommander(arguments);
try {
commands.parse(argv);
System.out.println(commands.getParsedCommand());
} catch (Exception e) {
System.out.println(e.getMessage());
commands.usage();
}
}
Once I run this class, I got : null as output. Seems like getParsedCommand() is not used as it should.
Can someone tell me how to use JCOmmmander methods correctly so I can see options given with arguments?
What I'm trying to do here is, once the user runs java -jar myApp.jar -port portNumber -h hostname -d database -c collection I wanna be able to get portNumber hostname database and collection value so I can establish a connexion and send queries.
Hope I was clear enough.
Ismail
You need to make a distinction between commands and parameters. In the example you give, you only need parameters.
The first chapter of the JCommander documentation provides a clear enough example of how to handle parameters. If your CommandLineArguments class is annotated as in the example, the parameter values should be correctly set in that class after calling parse(argv).
Commands are explained in a later chapter dealing with more complex command-line syntaxes.
I am using the JDI to debug another running java application.
What I do that works:
Run two applications using Eclipse. The debugger is launched with the following VM Options:
-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=4000
The other application connects to the socket at port 4000, and follows normal procedures (break points, etc.) to get a value of a Local Variable.
Works properly and gives me that value.
What I want to do now:
Instead of using Eclipse to launch two processes, I launch one in Eclipse, and that Process uses a ProcessBuilder to launch another one with the following arguments:
String[] args1 = {getJavaDir(),"-cp",classpath,"-Xdebug", "-Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=4000", "processII.Main2"};
ProcessBuilder builder = new ProcessBuilder(args1);
builder.directory(directory);
Process process = builder.start();
The process starts successfully. However, when I try to access it through the first process, I get the following Error:
com.sun.jdi.connect.IllegalConnectorArgumentsException: Argument invalid
Looked this up online, and there is little information about what the Exception is.
I would appreciate any help figuring out what the problem is!
This exception is throw when there is an error on the connector parameters to debug the JVM. I think that your debug parameters must go in the same argument together instead of two separate arguments (put -Xdebug with -Xrunjdwp... on the same argument), try with:
String[] args1 = {getJavaDir(),"-cp",classpath,"-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=4000", "processII.Main2"};
ProcessBuilder builder = new ProcessBuilder(args1);
builder.directory(directory);
Process process = builder.start();
Hope this helps,
You missed this code :import com.sun.jdi.connect.IllegalConnectorArgumentsException;
It depends on the jdk/lib/tool.jar.If you add this jar to you classpath,you can fixout your problem.
I am calling a jar via perl with the following command.
my $command = "$java_home/bin/java my_jar.jar ARG1 ARG2 ARG3";
my $result = `$command 2>&1;
However my JAR also expects arguments via STDIN. I need to know how to pass those arguments. I have tried passing them like normal arguments, and that didn't work. I read on a forum that OPEN2 might work however after reading the documentation I couldn't figure out how to make it work.
Any ideas on how to make this work would be great.
Thanks ahead of time.
Since you need to send and receive data from the Java process, you need two-way communication. That's what IPC::Open2 is designed to do. This allows you to create a dedicated pipe that renders STDIN/STDOUT unnecessary:
use IPC::Open2;
my $pid = open2( \*from_jar, \*to_jar, $command )
or die "Could not open 2-way pipe: $!";
print to_jar, "Here is input\n"; # Pass in data
my $result = <from_jar>; # Retrieve results
Also consider IPC::Open3 to handle errors as well.
Hello I am trying to pass arguments to my ImageJ PlugIn. However it seems no matter what I pass, argument string will be considered as empty by the program. I couldn't find any documentation on the internet about THAT issue.
My Java plugIn looks like this, and compiles fine.
import ij.plugin.PlugIn;
public class Test implements PlugIn {
public void run(String args) {
IJ.log("Starting plugin Test");
IJ.log("args: ." + args + ".");
}
}
I compile, make a .jar file and put it into the ImageJ plugins folder.
I can call it with the ImageJ userInterface (Plugin>Segmentation>Test) and the macro recorder will put the command used:
run("Test");
Then my code is executed, the log window pops-up as expected:
Starting plugin Test
args: ..
I can manually run the same command in a .ijm file, and get the same result.
However, when I run the following macro command:
run("Test", "my_string");
I get the same results in the log window:
Starting plugin Test
args: .. // <- I would like to get "my_string" passed there
Where it should have displayed (at least what I expect it to do)
Starting plugin Test
args: .my_string.
So my question is: how can I pass parameters to PlugIn and especially how to access them?
Many thanks
EDIT
Hey I found a way to bypass that:
Using the Macro.getOptions() : this method will retrieve the string passed in argument to the plugin.
However, I still can't find a way to pass more than 1 string argument. I tried overloading the PlugIn.run() method but it doesn't work at all.
My quick fix is to put all my arguments in 1 string, and separating them by a space. Then I split this string:
String [] arguments = Macro.getOptions().split(" ");
I don't see a more convenient way to get around that. I can't believe how stupid this situation is.
Please, if you have a better solution, feel free to share! Thanks
You are confusing the run(String arg) method in ij.plugin.Plugin with the ImageJ macro command run("command"\[, "options"\]), which calls IJ.run(String command, String options).
In the documentation for ij.plugin.Plugin#run(String arg), it says:
This method is called when the plugin is loaded. 'arg', which may be blank, is the argument specified for this plugin in IJ_Props.txt.
So, arg is an optional argument that you can use in IJ_Props.txt or in the plugins.config file of your plugin to assign different menu commands to different functions of your plugin (see also the excellent documentation on the Fiji wiki).
To make use of the options parameter when running your plugin from macro code, you should use a GenericDialog to get the options, or (as you apparently learned the hard way) use the helper function Macro.getOptions().
I would like to know if it is possible to get from code the command used to launch a java program.
E.g. if I launch a java program with:
java -cp lib1:lib2:... -jar mylib.jar com.foo.Bar
I would like to get the exact string (jvm parameters included).
Is it possible?
Comment on the bounty and the question
Thank you all for your responses. Unfortunately, I did not get the answer I was initally looking for. I was hoping there was some portable solution to get the complete java command from within the program itself (including classpath etc.). As it seems there are no portable solution and since I am using Linux I am using the responses of agodinhost and Luigi R. Viggiano to solve my problem. However I give the bounty to rahulroc for the most complete (portable) response. For the rest an upvote for all :)
The below mentioned code should show all JVM parameters, arguments passed to the main method as well as the main class name.
import java.lang.management.ManagementFactory;
import java.lang.management.RuntimeMXBean;
import java.util.List;
public static void main(String[] args) {
RuntimeMXBean bean = ManagementFactory.getRuntimeMXBean();
List<String> jvmArgs = bean.getInputArguments();
for (int i = 0; i < jvmArgs.size(); i++) {
System.out.println( jvmArgs.get( i ) );
}
System.out.println(" -classpath " + System.getProperty("java.class.path"));
// print the non-JVM command line arguments
// print name of the main class with its arguments, like org.ClassName param1 param2
System.out.println(" " + System.getProperty("sun.java.command"));
}
javadoc for getInputArguments
Returns the input arguments passed to the Java virtual machine which
does not include the arguments to the main method. This method returns
an empty list if there is no input argument to the Java virtual
machine.
Some Java virtual machine implementations may take input arguments
from multiple different sources: for examples, arguments passed from
the application that launches the Java virtual machine such as the
'java' command, environment variables, configuration files, etc.
Typically, not all command-line options to the 'java' command are
passed to the Java virtual machine. Thus, the returned input arguments
may not include all command-line options.
You can also take a look at : jps
It's a Java program that is able to get the full command line for all
Java processes, including full class name of main class and JVM
options.
You can find a good summary of various JVM tools, including
Java Application Launcher links to :
ManagementFactory.getRuntimeMXBean() - Returns the managed bean for the runtime system of the Java virtual machine.
getInputArguments() javadoc
determine if JVM is running in debug mode
You can use this to retrieve the VM parameters :
public static void main(String args[]) {
List<String> inputArguments = ManagementFactory.getRuntimeMXBean().getInputArguments();
System.out.println("input arguments = " + inputArguments);
}
However it won't give you all the command line (only gives the JVM arguments, no main class nor parameters). Sample output:
input arguments = [-Dfile.encoding=UTF-8, -XX:-UseTLAB, -Xms2000m, -Xmx2000m, -XX:+PrintCompilation, -XX:+PrintGC]
It only works on Sun Oracle JVM: System.getProperty("sun.java.command")
Additionally, you can have a look at JavaSysMon, it can report command line of active processes. To check which is the current JVM Process check here: How can a Java program get its own process ID?
in a linux machine would be easier to run:
ps -ef | grep java
this command will list all java programs running with it's used parameters.
Not sure about what can be used in a windows environment.
In the task manager on Win2003 you can enable the display of a column that displays the command like it does on linux. Or, you can do it from the command line like so:
wmic.exe PROCESS where "name like '%java%'" get Processid,Caption,Commandline