有没有办法重启JVM?就像在实际上没有退出,但关闭并重新加载所有类,并从顶部运行main?
答案 0 :(得分:17)
你最好的选择可能是在循环中运行java解释器,然后退出。例如:
#!/bin/sh
while true
do
java MainClass
done
如果您想要完全重启或关机,您可以测试退出状态:
#!/bin/sh
STATUS=0
while [ $STATUS -eq 0 ]
do
java MainClass
STATUS=$?
done
在java程序中,您可以使用System.exit(0)表示您要“重启”,并使用System.exit(1)表示您要停止并保持停止状态。
答案 1 :(得分:7)
IBM的JVM有一个名为“resettable”的功能,可以让你有效地做你想要的。
除了IBM JVM之外,我认为不可能。
答案 2 :(得分:2)
不是真正的“重启”,但是:
您可以构建自己的类加载器并使用它加载所有类(引导程序除外)。然后,当您想要“重新启动”时,请确保执行以下操作:
在Web服务器中“热插拔”Web应用程序时(在某种程度上)使用此过程。
请注意,静态类成员和JVM“全局”对象(由不受您控制的GC根访问的对象)将保留。例如,Locale.setLocale()在Locale上生成静态成员。由于Locale类由系统类加载器加载,因此不会“重新启动”。这意味着如果未明确清除,Locale.setLocale()中使用的旧Locale对象将在以后可用。
另一条路线是课堂教学。但是,由于我对它知之甚少,我对提供建议犹豫不决。
答案 3 :(得分:1)
如果您在应用程序服务器中工作,它们通常会带有内置的热部署机制,当您重新部署它时,它会重新加载应用程序中的所有类(Web应用程序,企业应用程序)。
否则,您将不得不考虑商业解决方案。 Java Rebel(http://www.zeroturnaround.com/javarebel/)就是这样一个选择。
答案 4 :(得分:0)
AFAIK没有这样的方法。
请注意,如果有办法做到这一点,它将高度依赖于当前加载的代码来正确释放所有保留的资源,以便提供正常的重启(想想文件,socket / tcp / http /数据库连接,线程等)。
某些应用程序(如Jboss AS)在控制台上捕获Ctrl + C并提供正常关闭,关闭所有资源,但这是特定于应用程序的代码,而不是JVM功能。
答案 5 :(得分:0)
我使用JMX做类似的事情,我将使用JMX“卸载”一个模块,然后“重新加载”它。在幕后我确信他们正在使用不同的类加载器。
答案 6 :(得分:0)
好吧,我目前有这个,它运行完美,完全独立于操作系统。唯一必须工作的是:执行没有任何路径/ etc的java进程,但我认为这也可以修复。
除了RunnableWithObject和restartMinecraft()之外,所有小代码都来自stackoverflow:)
你需要这样称呼它:
restartMinecraft(getCommandLineArgs());
基本上它的作用是:
是的,它直接来自我的我的Minecraft项目:)
代码:
Tools.isProcessExited()方法:
public static boolean isProcessExited(Process p) {
try {
p.exitValue();
} catch (IllegalThreadStateException e) {
return false;
}
return true;
}
Tools.restartMinecraft()方法:
public static void restartMinecraft(String args) throws IOException, InterruptedException {
//Here you can do shutdown code etc
Process p = Runtime.getRuntime().exec(args);
RunnableWithObject<Process> inputStreamPrinter = new RunnableWithObject<Process>() {
@Override
public void run() {
// TODO Auto-generated method stub
while (!Tools.isProcessExited(data)) {
try {
while (data.getInputStream().available() > 0) {
System.out.print((char) data.getInputStream().read());
}
} catch (IOException e) {
}
}
}
};
RunnableWithObject<Process> errorStreamPrinter = new RunnableWithObject<Process>() {
@Override
public void run() {
// TODO Auto-generated method stub
while (!Tools.isProcessExited(data)) {
try {
while (data.getErrorStream().available() > 0) {
System.err.print((char) data.getErrorStream().read());
}
} catch (IOException e) {
}
}
}
};
inputStreamPrinter.data = p;
errorStreamPrinter.data = p;
new Thread(inputStreamPrinter).start();
new Thread(errorStreamPrinter).start();
p.waitFor();
System.out.println("Minecraft exited. (" + p.exitValue() + ")");
System.exit(p.exitValue());
}
Tools.getCommandLineArgs()方法:
public static String getCommandLineArgs() {
String cmdline = "";
List<String> l = ManagementFactory.getRuntimeMXBean().getInputArguments();
cmdline += "java ";
for (int i = 0; i < l.size(); i++) {
cmdline += l.get(i) + " ";
}
cmdline += "-cp " + System.getProperty("java.class.path") + " " + System.getProperty("sun.java.command");
return cmdline;
}
Aaaaand最后是RunnableWithObject类:
package generic.minecraft.infinityclient;
public abstract class RunnableWithObject<T> implements Runnable {
public T data;
}
祝你好运:)
答案 7 :(得分:0)
在JavaX中很容易:您可以使用标准函数update data或nohupJavax()。