重新启动具有更大堆空间的JVM
我希望能够执行.Jar文件,如果堆空间设置得不够大,它应该启动一个具有相同.Jar文件的新JVM,但设置更大的堆空间,然后关闭第一个JVM和.Jar。
我尝试过使用ProcessBuilder,但我无法使用它。
它必须跨平台工作。
-ONi
我找到了解决方案,它可以跨平台工作。 要从代码重新启动JVM,请使用以下命令。 这个答案取自我在这里搜索数小时后发现的另一个问题。 如果需要,可以使用System.exit(0)跟随它,以在调用此方法后终止启动新进程的JVM。
public static void startSecondJVM() throws Exception { 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 = new ProcessBuilder(path, "-Xmx1024m", "-cp", classpath, Main.class.getName()); Process process = processBuilder.start(); }
您可以使用初始堆大小启动java,还可以指定仅在需要时使用的最大堆大小。 我不确定你要做什么,但它可能效仿你想要的行为?
java -Xms256m -Xmx1g -jar myapp.jar
在这个例子中,你从256M开始,如果应用程序需要更多内存,它将逐步增加,直到1G。
您可以尝试将这两个来源合并。
MemoryRecoveryTest.java
尝试从OutOfMemoryError
恢复。
/*License - LGPL Recovery from an OutOfMemory Error
The JavaDocs for Error state, in the first sentence..
"An Error is a subclass of Throwable that indicates serious problems that a reasonable application should not try to catch."
This advice has led to the fallacy that an OutOfMemoryError should not be caught and dealt with.But this demo. shows that it is quite easy to recover to the point of providing the user with meaningful information, and advice on how to proceed.
I aim to make my applications 'unreasonable'.;-) */ import java.awt.event.ActionListener; import java.awt.event.ActionEvent; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import javax.swing.JPanel; import javax.swing.JLabel; import javax.swing.JProgressBar; import javax.swing.JOptionPane; import javax.swing.JDialog; import javax.swing.Timer; import javax.swing.border.EmptyBorder; import java.util.ArrayList; /** A demo. showing recovery from an OutOfMemoryError. Our options once an OOME is encountered are relatively few, but we can still warn the end user and provide advice on how to correct the problem. @author Andrew Thompson */ public class MemoryRecoveryTest { public static void main(String[] args) { // reserve a buffer of memory byte[] buffer = new byte[2^10]; ArrayList
IWantToBeBig.java
确保在指定内存大小的情况下启动Process
。
import java.awt.EventQueue; import javax.swing.JOptionPane; import java.io.File; class IWantToBeBig { public static void main(String[] args) throws Exception { if (args.length==0) { ProcessBuilder pb = new ProcessBuilder( "java", "-jar", "-Xmx512m", "big.jar", "anArgument" ); pb.directory(new File(".")); Process process = pb.start(); process.waitFor(); System.out.println("Exit value: " + process.exitValue()); } else { Runnable r = new Runnable() { public void run() { JOptionPane.showMessageDialog( null, "Max Memory: " + Runtime.getRuntime().maxMemory() + " bytes."); } }; EventQueue.invokeLater(r); } } }
我在外部脚本文件中做这种工作 – 伪代码:
$heap := 128 $ok := true do { exitCode = java -Xmx$heapM -jar myApp.jar if (exitCode = OOME) { heap += 128 $ok := false } while(!$ok)
应始终可以捕获OOME并使用自定义代码退出。 这种方法存在一个问题 – 如果$ heap值超过了目标系统可能的最大堆空间(例如:Win32系统上的~1.4GByte),那么它将不会终止。
注意:这只是问题的答案 – 通常会分配大量内存和/或消除内存泄漏 – 但我不知道实际的要求/限制