Passing server argument in Eclipse and then reading it in application - java

I have Wildfly server in Eclipse Mars. In Open launch configuration, in section Program argumenst I have added Dmyarg.dir="Value".
Then, in application, I have code:
RuntimeMXBean mxBean = ManagementFactory.getRuntimeMXBean();
for(String arg : mxBean.getInputArguments()){
if(arg.startsWith("Dmyarg.dir")){
String [] filePath = arg.split("=");
break;
}
}
After running my server from Eclipse, there is no argument passed.
Afrer running my server by myself, my application can find this argument.
How can I add argument in Eclipse that would be displayed there?

According to RuntimeMXBean#getInputArguments documentation it
Returns the input arguments passed to the Java virtual machine which
does not include the arguments to the main method.
So if you want to see your argument in result of getInputArguments call you need to pass it to JVM. i.e. in Eclipse IDE you should type -Dmyarg.dir="Value" in "VM arguments" filed of launch configuration. And process it as
RuntimeMXBean mxBean = ManagementFactory.getRuntimeMXBean();
for(String arg : mxBean.getInputArguments()){
if(arg.startsWith("-Dmyarg.dir")){
String [] filePath = arg.split("=");
break;
}
}
Also note that you can use next code to get value of VM argument passed as -Dmyarg.dir="Value"
System.getProperty("myarg.dir")
See documentation for java command:
-Dproperty=value
Sets a system property value.
If value is a string that contains spaces, then you must enclose the
string in double quotation marks:
java -Dmydir="some string" SomeClass

Related

How can I handle spaces in arguments?

My app launches and loads the file if I do: myApp /file:c:\nospaces.asd from cmd but if I do myApp /file:c:\with spaces.asd it won't work because the program receives two arguments: myApp /file:c:\with and spaces.asd.
I know that I can do myApp "/file:c:\with spaces.asd" and it'll work like that from cmd. However this isn't a good solution because if I double click the .asd file (custom extension) (and select launch with my app) then main won't be getting the arguments as one line but as two arguments.
How can I go about fixing this issue so that my main will receive only one argument when double clicking the file?
You could join the arguments together if the file is not found. Something like this:
public static void main(String[] args) {
String fileName = joinArgumentsToValidFileName(args);
}
public static String joinArgumentsToValidFileName(String[] args) {
if(args.length == 0) {
return "";
}
String fileName = args[0];
int index = 1;
while(!new File(fileName).exists() && index < args.length) {
fileName += " " + args[index];
index++;
}
return fileName;
}
This assumes that the first argument (or the arguments) must be the file name. Any additional agruments could be evaluated by remembering the offset index somehow (not included in the code above).
But note: This is a not standard behavior of passing arguments to an application and could lead to cunfusion. So if you find a way to pass a "" wrapped file name argument, don't do this!
Double clicking to launch java would be affected by whats registered in windows related to the same i.e windows registry for jar-file launch command.
These are some similar questions asked on SO you can take a look at:
Running JAR file on Windows
java can run jar from cmd but not by double clicking
They mention the useful part which is ensuring you have the wildcard behind the executable in the registry c:\...\javaw.exe" -jar "%1" %

How to find list of java agents attached with a running JVM?

I am trying to debug an issue with the one of the java agents added to the production JVM.
In the start up script for the application java agent is properly added and has been working on other environments. But in production this agent does not seems to be working.
Is there any way to find list of java agents added ?
(This question is similar to Can a JVM retrieve a list of agents that have been loaded into it via the attach api?). For the sake of completeness, I will add this answer to both questions.)
Checking agents that have been added via command-line:
If you are interested in agents that were added to using the command line interface, you can check them by using the RuntimeMXBean.
This bean offers the method getInputArguments, which returns a list of all VM arguments.
You can iterate over the list and check it for the arguments agentpath, agentlib and javaagent, similar to the following code snippet:
RuntimeMXBean runtimeMXBean = ManagementFactory.getRuntimeMXBean();
List<String> jvmArgs = runtimeMXBean.getInputArguments();
System.out.println("JVM arguments:");
for (String arg : jvmArgs) {
if (arg.startsWith("-agentpath") || arg.startsWith("-agentlib") || arg.startsWith("-javaagent")) {
System.out.print("***** ");
}
System.out.print(arg);
if (arg.startsWith("-agentpath") || arg.startsWith("-agentlib") || arg.startsWith("-javaagent")) {
System.out.println(" *****");
} else {
System.out.println();
}
}
Checking agents that have been added using the Attach API:
If you are interested in the agents that have been added to an application at run time using the Attach API, you can use the DiagnosticCommandMBean.
This bean offers a diagnostic command called vmDynlib, a parameterless method that returns a String that list all dynamically loaded libraries.
Here is a snippet that prints all dynamic libraries loaded by the application's VM:
ObjectName diagnosticsCommandName = new ObjectName("com.sun.management:type=DiagnosticCommand");
String operationName = "vmDynlibs";
String result = (String) ManagementFactory.getPlatformMBeanServer().invoke(diagnosticsCommandName, operationName, null, null);
System.out.println(result);
This results in an output similar to this one:
Dynamic libraries:
0x00007ff7b8600000 - 0x00007ff7b8637000 C:\Program Files\Java\jdk1.8.0_181\bin\java.exe
0x00007ffdfeb00000 - 0x00007ffdfecf0000 C:\WINDOWS\SYSTEM32\ntdll.dll
0x00007ffdfe300000 - 0x00007ffdfe3b2000 C:\WINDOWS\System32\KERNEL32.DLL
0x00007ffdfbb30000 - 0x00007ffdfbdd3000 C:\WINDOWS\System32\KERNELBASE.dll
0x00007ffdfe950000 - 0x00007ffdfe9f3000 C:\WINDOWS\System32\ADVAPI32.dll
...
You can then check this text if it contains a certain .so or .dll file.
The same inspection can be performed non-programatically.
For this, you can use the jconsole tool.
Connect to a VM, switch to the tab MBeans, select com.sun.management, select DiagnosticCommand, select Operations, select vmDynlibs, and invoke it.
In the image, you can see one of my test agents attached to the application.
The agent was attached using the Attach API, thus this agent would not be visible by checking the application's command line arguments (i.e., no -agentpath=... would be seen on the arguments) but is only visible as dynamically loaded library.
You could use an extra designated agent (attached using premain) to list down all the other agents.
This agent must be the first in the list to the java command for launching your production JVM.
Whenever any class gets added, check if it has an agentmain(String, Instrumentation) or premain(String, Instrumentation) signature method. If so, you have an agent match.

Packaging a jar with preconfigured command line arguments

I am wondering if there's a way to create a jar that includes some command line arguments in it, the arguments that are usually passed in the command line when one tries to start up the jar (these parameters are then passed on to the main function). Basically instead of starting my app with
java -jar myapp.jar "arg1" "arg2", I want to start my app with
java -jar myapp.jar
and have "arg1" and "arg2" passed to the main function.
The reason behind this is that I want to deploy this to different environments, and I want my jar to contain different parameters according to the environment it's being deployed at.
Maybe there's another way to achieve similar results ??
Cheers.
PS: Looking for a maven solution.
Edit: I'll add a complete example to make this a bit more clear:
Let's say I have 2 environments: "Production" and "Test". I want to run the jar in the same way no matter in what environment I deploy it. So I always want to run it with:
java -jar myapp.jar
But! In order for my 2 environments to run ok, I need the Production environment jar to start it's main method with an argument "prod" and I need the Test environment jar to start it's main method with an argument "test".
If I correctly understood your problem, in your main() you could define a simple logic to handle the case where you do not specify any input parameter; the logic could retrieve the desired values according to the correct platform/env.
As an example:
public class Test01
{
public static void main(String... aaa)
{
// Check input
if(aaa.length == 0) {
/* Insert logic to retrieve the value you want, depending on the platform/environment.
* A trivial example could be: */
aaa = new String[2];
aaa[0] = "First value";
aaa[1] = "Second value";
}
// Processing, e.g. print the 2 input values
System.out.println(aaa[0] + ", " + aaa[1]);
}
}
Fyi, I created a runnable jar using eclipse, and start the application by either
java -jar Test01.jar
or
java -jar Test01.jar arg1 arg2
Hope this helps!
One solution is to change main(String[] args) to get values from env var if they are not present in the passed arguments.
String user;
String password;
if(args.length < 2)
{
user = System.getenv("appUser");
password = System.getenv("appPassword");
} else {
user = args[0];
password = args[1];
}
You can also create another class with a main function that will call the real one.
public class CallerMyApp{
public void main(String[] args) {
String[] realArgs = {System.getenv("appUser"), System.getenv("appPassword")};
MyApp.main(realArgs);
}
}
Then to execute its something like
java -cp myapp.jar CallerMyApp

how to configure eclipse run configurations for System Properties (ssl/tls) in command line arguments

My command line input is when I run without IDE, java -
Djavax.net.ssl.trustStore="d:/xxxLS/xxxx.jks"
-Djavax.net.ssl.trustStorePassword=posclient
pDevice.ClientMain 1 d:/xxxLS/xxsSslxxxClient.jks
possslandencryptclient possslclient posencryptclient localhost 7866 SslYes EncYes
When I try to run the application in Eclipse, it not works. How to specify SSL/TLS key path in Eclipse. I have key files in my disk.(xxxx.jks, xxsSslxxxClient.jks)
I don't know how to configure my eclipse for the specific command line arguments.
file name (to be excecuted) Device.ClientMain
Please help me.
Yes, I got solution where to place the TLS/SSL keys in the eclipse Run -> Run Configurations -> under Main select the class which going to run, -> (X)Arguments provide the key details which you to include under the VM arguments,under Program Arguments pass the usual command line arguments. When running SSL layer client/server applications key list or key details should be included under the VM arguments. My program works well.
In Details, Arguments are divided into Program Arguments, VM arguments in Eclipse, Program arguments are arguments that are passed to your application, which are accessible via the "args" String array parameter of your main method. VM arguments are arguments such as System properties that are passed to the Java s w interpreter.
The VM arguments go after the call to your Java interpreter (ie, 'java') and before the Java class. Program arguments go after your Java class.
Public class ArgsTest {
public static void main(String[] args) throws IOException {
System.out.println("Program Arguments:");
for (String arg : args) {
System.out.println("\t" + arg);
}
System.out.println("System Properties from VM Arguments");
String sysProp1 = "sysProp1";
System.out.println("\tName:" + sysProp1 + ", Value:" + System.getProperty(sysProp1));
String sysProp2 = "sysProp2";
System.out.println("\tName:" + sysProp2 + ", Value:" + System.getProperty(sysProp2));
}
}
Pass input as, java ArgsTest -DsysProp1=sp1 -DsysProp2=sp2 pro1 pro2 pro3
Output would be:
Program Arguments:
pro1
pro2
pro3
System Properties from VM Arguments
Name:sysProp1, Value:sp1
Name:sysProp2, Value:sp2

Is it possible to get the command used to launch the jvm in java?

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

Categories

Resources