package edu.oregonstate.cartography.app;
import java.io.File;
import java.io.IOException;
import java.lang.management.ManagementFactory;
/**
* Launch process with maximum possible heap space. Code parts from Whitebox GAT
* http://www.uoguelph.ca/~hydrogeo/Whitebox/
* A process can only be launched once.
*
* @author Bernhard Jenny, Cartography and Geovisualization Group, Oregon State
* University
*/
public class ProcessLauncher {
/**
* The size of the desired heap in MB. This is currently determined
* heuristically by findMaximumHeapSize.
*/
private int heapSizeMB;
/**
* The launched process.
*/
private Process process = null;
public ProcessLauncher() {
findMaximumHeapSize();
}
/**
* Finds the maximum heap size and stores the result in this.heapSizeMB.
*/
private void findMaximumHeapSize() {
long ONE_GB = 1024 * 1024 * 1024;
long amountOfMemory = ((com.sun.management.OperatingSystemMXBean) ManagementFactory.getOperatingSystemMXBean()).getTotalPhysicalMemorySize();
if (System.getProperty("sun.arch.data.model").contains("32")) {
if (196608 < amountOfMemory / 2) {
heapSizeMB = 1200;
} else {
heapSizeMB = (int) (amountOfMemory / 2);
}
} else {
// reserve one third of total memory or 512 MB for other processes,
// whatever is smaller.
int heapReserve = (int) Math.min(amountOfMemory / 3, ONE_GB / 2);
heapSizeMB = (int) ((amountOfMemory - heapReserve) / 1024 / 1024);
if (heapSizeMB <= 500) {
heapSizeMB = 1000;
}
}
}
/**
* Returns the file path for an icon file in an OS X app bundle.
* @param fileName Name of the icon file.
* @return The path to the icon file.
*/
public String findXDockIconPath(String fileName) {
try {
String applicationDirectory = java.net.URLDecoder.decode(getClass().getProtectionDomain().getCodeSource().getLocation().getPath(), "UTF-8");
applicationDirectory = new File(applicationDirectory).getParent();
// step one level up out of the "Java" directory
applicationDirectory = new File(applicationDirectory).getParent();
if (!applicationDirectory.endsWith(File.separator)) {
applicationDirectory += File.separator;
}
// one level down into the "Resources" directory
applicationDirectory += "Resources" + File.separator;
return applicationDirectory + fileName;
} catch (Throwable ex) {
return "";
}
}
/**
* Starts a new process and calls the main method of a specified class.
*
* @param className The class with the main method.
* @param xDockName The name to display in the OS X dock.
* @param xDockIconPath The icon to display in the OS X dock.
* @throws IOException Exception if the executable file cannot be found or
* launched.
*/
public void startJVM(String className, String xDockName, String xDockIconPath) throws IOException {
if (process != null) {
throw new IllegalStateException("process already launched");
}
String xmx = "-Xmx" + heapSizeMB + "M";
String xms = "-Xms" + heapSizeMB + "M";
String separator = System.getProperty("file.separator");
String classpath = System.getProperty("java.class.path");
String path = System.getProperty("java.home")
+ separator + "bin" + separator + "java";
ProcessBuilder processBuilder;
if (System.getProperty("os.name").contains("Mac")) {
processBuilder = new ProcessBuilder(path, xmx, xms,
"-cp", classpath,
"-Xdock:name=" + xDockName,
"-Xdock:icon=" + xDockIconPath,
className);
} else {
processBuilder = new ProcessBuilder(path, xmx, xms, "-cp", classpath, className);
}
process = processBuilder.start();
}
}