Java 有什么方法可以“重新启动”JVM?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/259343/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Any way to "reboot" the JVM?
提问by Alex
Is there any way to reboot the JVM? As in don't actually exit, but close and reload all classes, and run main from the top?
有没有办法重新启动JVM?因为实际上并没有退出,而是关闭并重新加载所有类,然后从顶部运行 main?
采纳答案by Andru Luvisi
Your best bet is probably to run the java interpreter within a loop, and just exit. For example:
最好的办法可能是在循环中运行 java 解释器,然后退出。例如:
#!/bin/sh
while true
do
java MainClass
done
If you want the ability to reboot or shutdown entirely, you could test the exit status:
如果您希望能够完全重新启动或关闭,您可以测试退出状态:
#!/bin/sh
STATUS=0
while [ $STATUS -eq 0 ]
do
java MainClass
STATUS=$?
done
Within the java program, you can use System.exit(0) to indicate that you want to "reboot," and System.exit(1) to indicate that you want to stop and stay stopped.
在 java 程序中,您可以使用 System.exit(0) 指示您要“重新启动”,使用 System.exit(1) 指示您要停止并保持停止状态。
回答by Miguel Ping
AFAIK there is no such way.
AFAIK 没有这样的方法。
Notice that if there were a way to do that, it would highly depend on the current loaded code to properly release all held resources in order to provide a graceful restart (think about files, socket/tcp/http/database connections, threads, etc).
请注意,如果有办法做到这一点,它将高度依赖当前加载的代码来正确释放所有持有的资源以提供优雅的重启(考虑文件、socket/tcp/http/数据库连接、线程等)。
Some applications, like Jboss AS, capture Ctrl+C on the console and provide a graceful shutdown, closing all resources, but this is application-specific code and not a JVM feature.
一些应用程序,如 Jboss AS,在控制台上捕获 Ctrl+C 并提供正常关闭,关闭所有资源,但这是特定于应用程序的代码,而不是 JVM 功能。
回答by DustinB
IBM's JVM has a feature called "resettable" which allows you to effectively do what you are asking.
IBM 的 JVM 有一个称为“可重置”的特性,它允许您有效地执行您所要求的操作。
Other than the IBM JVM, I don't think it is possible.
除了 IBM JVM,我认为这是不可能的。
回答by Hyman Leow
If you're working in an application server, they typically come with built-in hot deployment mechanisms that'll reload all classes in your application (web app, enterprise app) when you redeploy it.
如果您在应用程序服务器中工作,它们通常带有内置的热部署机制,当您重新部署应用程序(Web 应用程序、企业应用程序)时,这些机制将重新加载应用程序中的所有类。
Otherwise, you'll have to look into commercial solutions. Java Rebel (http://www.zeroturnaround.com/javarebel/) is one such option.
否则,您将不得不寻找商业解决方案。Java Rebel ( http://www.zeroturnaround.com/javarebel/) 就是这样一种选择。
回答by Javamann
I do something similar using JMX, I will 'unload' a module using JMX and then 'reload' it. Behind the scenes I am sure they are using a different class loader.
我使用 JMX 做类似的事情,我将使用 JMX“卸载”一个模块,然后“重新加载”它。在幕后,我确信他们使用的是不同的类加载器。
回答by Ran Biron
Not a real "reboot" but:
不是真正的“重启”,而是:
You can build your own class loader and load all your classes (except a bootstrap) with it. Then, when you want to "reboot", make sure you do the following:
您可以构建自己的类加载器并使用它加载所有类(引导程序除外)。然后,当您想“重新启动”时,请确保执行以下操作:
- End any threads that you've opened and are using your classes.
- Dispose any Window / Dialog / Applet you've created (UI application).
- Close / dispose any other GC root / OS resources hungry peered resource (database connections, etc).
- Throw away your customized class loader, create another instance of it and reload all the classes. You can probably optimize this step by pre-processing the classes from files so you won't have to access the codebase again.
- Call your main point of entry.
- 结束您已打开并正在使用您的类的任何线程。
- 处置您创建的任何窗口/对话框/小程序(UI 应用程序)。
- 关闭/处置任何其他 GC 根/操作系统资源饥饿的对等资源(数据库连接等)。
- 扔掉你自定义的类加载器,创建它的另一个实例并重新加载所有类。您可以通过预处理文件中的类来优化此步骤,这样您就不必再次访问代码库。
- 致电您的主要入口点。
This procedure is used (to some extent) while "hot-swapping" webapps in web servers.
此过程(在某种程度上)用于在 Web 服务器中“热交换”Web 应用程序。
Note though, static class members and JVM "global" objects (ones that are accessed by a GC root that isn't under your control) will stay. For example, Locale.setLocale() effects a static member on Locale. Since the Locale class is loaded by the system class loader, it will not be "restarted". That means that the old Locale object that was used in Locale.setLocale() will be available afterward if not explicitly cleaned.
但请注意,静态类成员和 JVM“全局”对象(由不受您控制的 GC 根访问的对象)将保留。例如, Locale.setLocale() 影响 Locale 上的静态成员。由于 Locale 类是由系统类加载器加载的,因此不会“重新启动”。这意味着如果没有明确清除,在 Locale.setLocale() 中使用的旧 Locale 对象将在之后可用。
Yet another route to take is instrumentation of classes. However, since I know little of it, I'm hesitant to offer advice.
另一种方法是使用类仪器。但是,由于我对此知之甚少,所以我犹豫是否提供建议。
回答by 2xsaiko
Well, I currently have this, it works perfectly, and completely OS-independent. The only thing that must work: executing the java process without any path/etc, but I think this can also be fixed.
嗯,我目前有这个,它工作得很好,并且完全独立于操作系统。唯一必须做的事情:在没有任何路径/等的情况下执行 java 进程,但我认为这也可以解决。
The little code pieces are all from stackoverflow except RunnableWithObject and restartMinecraft() :)
除了 RunnableWithObject 和 restartMinecraft() 外,其他小代码都来自 stackoverflow :)
You need to call it like this:
你需要这样称呼它:
restartMinecraft(getCommandLineArgs());
So what it basically does, is:
所以它的基本作用是:
- Spawns a new Process and stores it in the p variable
- Makes two RunnableWithObject instances and fills the process object into their data value, then starts two threads, they just print the inputStream and errorStream when it has available data until the process is exited
- Waits for the process to exit
- prints debug message about process exit
- Terminates with the exit value of the process(not necessary)
- 生成一个新进程并将其存储在 p 变量中
- 创建两个 RunnableWithObject 实例并将进程对象填充到它们的数据值中,然后启动两个线程,当有可用数据时,它们只打印 inputStream 和 errorStream 直到进程退出
- 等待进程退出
- 打印有关进程退出的调试消息
- 以进程的退出值终止(不必要)
And yes it is directly pulled from my minecraft project:)
是的,它是直接从我的 Minecraft 项目中提取的:)
The code:
编码:
Tools.isProcessExited() method:
Tools.isProcessExited() 方法:
public static boolean isProcessExited(Process p) {
try {
p.exitValue();
} catch (IllegalThreadStateException e) {
return false;
}
return true;
}
Tools.restartMinecraft() method:
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() method:
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 finally the RunnableWithObject class:
Aaaa,最后是 RunnableWithObject 类:
package generic.minecraft.infinityclient;
public abstract class RunnableWithObject<T> implements Runnable {
public T data;
}
Good luck :)
祝你好运 :)
回答by Stefan Reich
It's easy in JavaX: You can use the standard functions nohupJavax()or restart().
在 JavaX 中很容易:您可以使用标准函数nohupJavax()或restart()。