views:

53

answers:

1

Hello ,

The same old problem ... I want to run my jar on Mac or Linux with high memory allocation. I do not want the user to open the Terminal and write java -XMx512 -jar MainJar.jar manually.

I have seen a lot of solutions to fix this ... But i was wondering if this might work : "Executing the Terminal command java -XMx512 -jar MainJar.jar in Jar(B) to initialize Jar(A) with 512 MB memory allocation.".

In Jar(B) i have tried this code to run Jar(A) and it worked fine :

public static void main(String[] args) throws Exception{
   String jarName = "MainJar.jar";  // Jar(A) name.
   Desktop.getDesktop().open( new File( jarName ) );
}

But still i did not allocate memory for Jar(A) when initialized from Jar(B), so can i write a code in Jar(B) to run the Terminal and give it the command to execute it : "java -XMx512 -jar MainJar.jar" ?

------------------------------ Edited as requested to be more clear.

+2  A: 

You can use Runtime.exec() or a ProcessBuilder to accomplish this.

Process proc = new ProcessBuilder("java", "-XMx512M", "-jar", "MainJar.jar").start();
int result = proc.waitFor();

But honestly I think it's an awful solution. I would favour an installation package like InstallAnywhere. Failing that I would use a shell script to launch the Jar. Encapsulating it in a Jar where it can't be edited is annoying to users and now you have parallel dependencies rather than a single file.

If you were going to take this route, it would be possible to use the same Jar for both purposes. Add your class file to launch with the correct parameters to the Jar, say AppLauncher.class. We'll assume your program's real code starts at Main.class.

public class AppLauncher {
     public static void main(String... args) {
        Process proc = new ProcessBuilder("java", "-XMx512M", "-cp", "MyJar.jar", "Main").start();
        int result = proc.waitFor();
     }
}

Then you would have your Manifest file of the jar point to this main class:

 Main-Class: AppLauncher

You would then execute this jar via

java -jar MyJar.jar

Or through file associations (double click).

When it runs, it executes the command java -Xmx512M -cp MyJar.jar Main which runs the main method of the Main class of your jar. The same jar is used in both invocations: the first time it automatically runs AppLauncher.main() via the manifest file, the second time Main.main() via an explicit process call.

This is still fragile of course. For one thing, it assumes that the working directory is set to the folder that contains your jar file. That's not always true.

Edit: Just in case you're not convinced to do otherwise, and actually take the ProcessBuilder route, there's more to it than just what I noted. There are pitfalls to avoid. For instance, I didn't read from the process's output stream (using Process.getInputStream()) so if child Java process outputs anything to stdout, it will freeze when the OS buffer is filled.

Mark Peters
@Mark : I like the idea of executing the command from the same Jar ... But i still can't get how to do it. What will i write in the 1st Main-Class ?
Brad
@Brad: I hope @Mark doesnt get upset for stealing his thunder, but what he suggests, I believe, is that you write that code in your small jar (B). When you run (B) it then creates a `Process` which then executes your main jar (A). Take a look at http://download.oracle.com/javase/1.4.2/docs/api/java/lang/Process.html
posdef
@Brad I updated my answer to expand on that point.
Mark Peters
@Mark: Thanks a lot Mark ... I think i am convinced that using this solution is not stable. I am trying now to use a shell script. I hope it will run fine.
Brad