0

I have written a Java application which is now compiled into a jar. Inside the applications main method I want to have the following:

Runtime.exec("java -jar myapp.jar arg1 arg2"))

(Or with Processbuilder if it's better)

I.e. the application should fork itself and create new processes.

So far, so good... my problem is now that I think that I cannot just call "java" but I have to give the full path to the java directory and I also think that I have to give the full path to myapp.jar.

Is there a way to avoid hardcoding the full path? I.e. that the java path and the path to myapp.jar is inferred at runtime inside the Runtime.exec?

Moreover, is it possible that the application can infer its name at runtime? I.e. the applications name is myapp.jar but I don't want to hardcode it in the Runtime.exec(...).

Edit: I need it on Ubuntu but also running in Windows.

1

1 Answer 1

1

Option 1

Use Runtime.getRuntime().exec:

Process proc = Runtime.getRuntime().exec(new String[] {"java","-jar","myapp.jar","arg1","arg2"});

Doing getRuntime() should infer where the Java executable should be.

Option 2

Use ProcessBuilder:

ProcessBuilder pb = new ProcessBuilder("java","-jar","myapp.jar","arg1","arg2");
Process p = pb.start();

As noted in the documentation about the environment: The initial value is a copy of the environment of the current process (see System.getenv()).

Option 3

Load the file into your classpath and then call the main method directly:

File file = new File("/path/to/myapp.jar");    
JarFile jarFile = new JarFile(file);  
Manifest manifest = jarFile.getManifest();
if (manifest != null) {
    Attributes attributes = manifest.getMainAttributes();  
    String className = attributes.getValue(Attributes.Name.MAIN_CLASS);
    URLClassLoader loader = new URLClassLoader(new URL[] { file.toURI().toURL() }); 
    Class<?> cls = loader.loadClass(className);
    Method main = cls.getDeclaredMethod("main", String[].class);  
    String[] args = {"arg1", "arg2"};  
    main.invoke(null, args); // static methods are invoked with null as first argument
} else {
    System.err.println("Cannot run " + file);
}
Sign up to request clarification or add additional context in comments.

6 Comments

Thank you. Do I don't need to give the path to the java executable, i.e. home/bin/java?
Runtime.getRuntime() is your current environment (which knows where java is, so no, you shouldn't need to give the path to it.
Thank you so much. Which one of the three options is the best?
The second, now third, approach of loading from the classpath is just another way of doing it. It can give you greater control and possibly help front load the classes you will be calling earlier to hopefully make a 'snappier' load when you execute the main class. A downside to it can be collisions of namespaces (just speculating this, haven't tried it) - duplicate classes being loaded.
And what is the benefit of option 2 over option 1?
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.