In Java, is there a way to get command line parameters even if main () did not save them?

We have a program with main () that parses specific CLPs but doesn't save them anywhere. Then I have my own plug-in code that needs access to the source CLP (so that I can pass more parameters). However, I cannot change main ()

I saw that there seems to be a way to do this in C # , I'm looking for an equivalent Java solution for Linux.

UPDATE: Obviously, I know how main () works. Unfortunately, I cannot modify an existing application or the way it is called (except for CLP). I can access only through the isolated code of the plugin. My question is whether there is a way to get the command line (and not environment variables with -D) that the JVM was called from.

+4
source share
5 answers

Besides the fact that I mainly do this, I think that the only other option you have is to go to the operating system level and execute some commands to get the arguments.

In linux, the cmd line arguments for the current process are stored in / proc / pid / cmdline

So, to get them, you will need to find the process ID. See here:

How can a Java program get its own process id?

Then, using this open / proc / pid / cmdline and analyze it. The format of this file and example in c:

http://www.unix.com/unix-advanced-expert-users/86740-retrieving-command-line-arguments-particular-pid.html

It is best to wrap these two calls in one shell script that you call from java.

Please note that this will be extremely unbearable and a bit hacked. But if needs should ...

+4
source

The solution is easy after you realize that the main Java method is another static method that takes a String array as an argument.

Create a new class that stores the CLP and then calls the old class. You can later access your CLP with the new class:

import NotToBeChangedMainClass; public MyMainClass { public static final String[] ARGUMENTS; public static void main(String ... args) { ARGUMENTS = args; NotToBeChangedMainClass.main(args); } 

}

Finally, modify any external caller (such as any batch files) to use MyMainClass instead of NotToBeChangedMainClass. If you use smooth banks or something similar, this requires a change in the corresponding configuration file.

+4
source

Create your own main class. Save the arguments. Call the old main .

On the command line (before the name of the main class or -jar ) it may be easier to use System.getProperty and -Dkey=value .

+1
source

If you have no choice, you absolutely need to keep all existing class names with their exact name ( as indicated in your comment , to my previous answer), then you should go with AspectJ.

Consider this class:

 public class UnmodifyableClassWithMain { public static void main(String[] args) { System.out.println("In main"); new ClassUsingArgumentRegistry(); } } 

First, you need something that contains command line arguments. For simplicity, I will use a simple class with a static field:

 public class ArgumentRegistry { public static String[] ARGS; } 

Then you need to define an Aspect that intercepts calls to the main one and stores the arguments.

 public aspect StoreArgumentsOfMain { /** * This pointcut intercepts all calls to methods called main with a string array as * argument. */ pointcut mainMethod(String[] arguments): execution(void main(String[])) && args(arguments); /** * Before the original main method gets called, store the arguments in the registry. */ before(String[] arguments): mainMethod(arguments) { System.out.println("Storing arguments"); ArgumentRegistry.ARGS = arguments; } } 

To test this, I also created the ClassUsingArgumentRegistry class:

 public class ClassUsingArgumentRegistry { public ClassUsingArgumentRegistry() { System.out.println("Arguments: " + java.util.Arrays.toString(ArgumentRegistry.ARGS)); } } 

What is it. If I turn on AspectJ time compilation and run the result using "java UnmodifyableClassWithMain Foo Bar Baz", I get the following output:

 Storing arguments In main Arguments: [foo, bar, baz] 
+1
source

Please note that this solution is very limited, since Linux truncates from the command line that it saves. Since Java command lines often have very long class paths, this is a very real problem.

Here is the Java code that implements the answer given by Pablojim.

 package test; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.List; public class Test { public static List<String> getLinuxCmdline(int maxBytesToRead) throws IOException { List<String> result = new ArrayList<>(); String pid = new File("/proc/self").getCanonicalFile().getName(); File cmdlineFile = new File("/proc/" + pid + "/cmdline"); final int growBy = 1024; try (FileInputStream is = new FileInputStream(cmdlineFile);) { byte[] data = new byte[Math.min(growBy, maxBytesToRead)]; int totalRead = 0; while (totalRead < maxBytesToRead) { int read = is.read(data, totalRead, data.length - totalRead); if (read > 0) { totalRead += read; if (data.length == totalRead) { data = Arrays.copyOf(data, Math.min(data.length + growBy, maxBytesToRead)); } } else { break; } } int start = 0; int scan = 0; while (scan < totalRead) { if (data[scan] == 0) { result.add(new String(Arrays.copyOfRange(data, start, scan))); start = scan + 1; } scan++; } if (scan - start > 0) result.add(new String(Arrays.copyOfRange(data, start, scan))); } return result; } public static void main(String[] args) throws IOException { System.out.println(getLinuxCmdline(Integer.MAX_VALUE)); } } 

Running this with the "foo bar" arguments in Eclipse gives this for me:

 [/usr/lib/jvm/java-8-oracle/bin/java, -Dfile.encoding=UTF-8, -classpath, /home/mab/workspace/test/bin, test.Test, foo, bar] 
0
source

All Articles