有什么方法可以“重启”JVM?
有没有办法重启JVM? 就像在实际上不退出,但关闭并重新加载所有类,并从顶部运行main?
你最好的选择可能是在循环中运行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)来指示您要停止并保持停止状态。
IBM的JVM有一个名为“resettable”的function,可以让你有效地做你想要的。
除了IBM JVM之外,我认为不可能。
不是真正的“重启”但是:
您可以构建自己的类加载器并使用它加载所有类(引导程序除外)。 然后,当您想要“重新启动”时,请确保执行以下操作:
- 结束您打开并正在使用您的类的所有线程。
- 处理您创建的任何窗口/对话框/小程序(UI应用程序)。
- 关闭/处置任何其他GC根/ OS资源饥饿的对等资源(数据库连接等)。
- 丢弃您的自定义类加载器,创建它的另一个实例并重新加载所有类。 您可以通过预处理文件中的类来优化此步骤,这样您就不必再次访问代码库。
- 致电您的主要入口。
在Web服务器中“热交换”Web应用程序时(在某种程度上)使用此过程。
但请注意,静态类成员和JVM“全局”对象(由不受您控制的GC根访问的对象)将保留。 例如,Locale.setLocale()在Locale上生成静态成员。 由于Locale类由系统类加载器加载,因此不会“重新启动”。 这意味着如果未明确清除,Locale.setLocale()中使用的旧Locale对象将在以后可用。
还有另一种方法是上课。 但是,由于我对它知之甚少,我对提供建议犹豫不决。
有关热部署的说明以及一些示例
如果您在应用程序服务器中工作,它们通常会带有内置的热部署机制,当您重新部署它时,它会重新加载应用程序中的所有类(Web应用程序,企业应用程序)。
否则,您将不得不考虑商业解决方案。 Java Rebel( http://www.zeroturnaround.com/javarebel/ )就是这样一个选择。
AFAIK没有这样的方式。
请注意,如果有办法做到这一点,它将高度依赖于当前加载的代码来正确释放所有保留的资源,以便提供正常的重新启动(考虑文件,socket / tcp / http /数据库连接,线程等)。
某些应用程序(如Jboss AS)在控制台上捕获Ctrl + C并提供正常关闭,关闭所有资源,但这是特定于应用程序的代码而不是JVMfunction。
我使用JMX做类似的事情,我将使用JMX“卸载”一个模块然后“重新加载”它。 在幕后我肯定他们正在使用不同的类加载器。
好吧,我目前有这个,它运行完美,完全独立于操作系统。 唯一必须工作的是:执行没有任何路径/ etc的java进程,但我认为这也可以修复。
除了RunnableWithObject和restartMinecraft()之外,这些小代码都来自stackoverflow。
你需要像这样调用它:
restartMinecraft(getCommandLineArgs());
它的基本function是:
- 生成一个新进程并将其存储在p变量中
- 制作两个RunnableWithObject实例并将进程对象填充到其数据值中,然后启动两个线程,它们只有在有可用数据时才打印inputStream和errorStream,直到退出进程
- 等待进程退出
- 打印有关进程退出的调试消息
- 终止具有进程的退出值(不必要)
是的,它直接从我的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 inputStreamPrinter = new RunnableWithObject () { @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 errorStreamPrinter = new RunnableWithObject () { @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 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 implements Runnable { public T data; }
祝你好运 :)
在JavaX中很容易:您可以使用标准函数nohupJavax()或restart() 。
- Java 7,使用HTML格式标签时按钮文本的颜色
- 如何在不加载JPA中的相关实体的情况下使用外键保存实体?
- 只是获取id列值而不是在hibernate对象中使用join一对多关系
- Java致命错误SIGSEGV
- 试图在Spring WebFlow Project的服务级别上运行junit测试。 假设$ AssumptionViolatedException
- 未设置’hibernate.dialect’时,连接不能为空
- 如果不专注于JavaFX阶段,如何获得键盘输入?
- 使用javax.sound.sampled.Clip在游戏中播放,循环和停止多个声音。 意外错误
- 如何在JLabel上放置一个计时器来每秒更新一次