Java “有什么办法吗?”;“重新启动”;JVM?

Java “有什么办法吗?”;“重新启动”;JVM?,java,jvm,Java,Jvm,有没有办法重新启动JVM?如中所示,不实际退出,而是关闭并重新加载所有类,并从顶部运行main?AFAIK没有这种方法 请注意,如果有一种方法可以做到这一点,那么它将高度依赖于当前加载的代码来正确释放所有保留的资源,以便提供良好的重启(考虑文件、套接字/tcp/http/数据库连接、线程等) 有些应用程序,如Jboss AS,在控制台上捕获Ctrl+C并提供优雅的关闭,关闭所有资源,但这是特定于应用程序的代码,而不是JVM特性。IBM的JVM有一个称为“可重置”的特性,允许您有效地执行要求的操作

有没有办法重新启动JVM?如中所示,不实际退出,而是关闭并重新加载所有类,并从顶部运行main?

AFAIK没有这种方法

请注意,如果有一种方法可以做到这一点,那么它将高度依赖于当前加载的代码来正确释放所有保留的资源,以便提供良好的重启(考虑文件、套接字/tcp/http/数据库连接、线程等)


有些应用程序,如Jboss AS,在控制台上捕获Ctrl+C并提供优雅的关闭,关闭所有资源,但这是特定于应用程序的代码,而不是JVM特性。

IBM的JVM有一个称为“可重置”的特性,允许您有效地执行要求的操作


除了IBM JVM之外,我认为这是不可能的。

如果您在应用程序服务器中工作,它们通常带有内置的热部署机制,当您重新部署应用程序(web应用程序、企业应用程序)时,这些机制将重新加载应用程序中的所有类


否则,您将不得不研究商业解决方案。Java Rebel()就是这样一个选项。

您最好的选择可能是在循环中运行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)表示要停止并保持停止。

我使用JMX执行类似操作,我将使用JMX“卸载”模块,然后“重新加载”。在幕后,我确信他们使用的是不同的类加载器。

不是真正的“重新启动”,而是:

您可以构建自己的类加载器,并用它加载所有类(引导除外)。然后,当您要“重新启动”时,请确保执行以下操作:

  • 结束所有已打开并正在使用类的线程
  • 处理您创建的任何窗口/对话框/小程序(UI应用程序)
  • 关闭/处置任何其他需要对等资源(数据库连接等)的GC根/OS资源
  • 扔掉定制的类加载器,创建它的另一个实例并重新加载所有类。您可能可以通过预处理文件中的类来优化此步骤,这样就不必再次访问代码库
  • 打电话给你的主要入口
  • 在web服务器中“热插拔”web应用程序时(在某种程度上)会使用此过程

    不过请注意,静态类成员和JVM“全局”对象(由不受您控制的GC根访问的对象)将保持不变。例如,Locale.setLocale()影响Locale上的静态成员。由于Locale类是由系统类加载器加载的,因此不会“重新启动”。这意味着,如果没有显式清理,Locale.setLocale()中使用的旧Locale对象将在以后可用

    另一种方法是类的插装。然而,因为我对它知之甚少,所以我不愿提供建议


    好吧,我现在有这个,它工作完美,完全独立于操作系统。唯一必须工作的事情是:在没有任何路径/等的情况下执行java进程,但我认为这也是可以解决的

    除了runnableithobject和restartMinecraft():)之外,这些小代码都来自stackoverflow

    你需要这样称呼它:

    restartMinecraft(getCommandLineArgs());
    
    所以它的基本功能是:

  • 生成一个新进程并将其存储在p变量中
  • 生成两个RunnableWithObject实例并将流程对象填充到其数据值中,然后启动两个线程,当有可用数据时,它们只打印inputStream和errorStream,直到流程退出
  • 等待进程退出
  • 打印有关进程退出的调试消息
  • 以进程的退出值终止(不需要)
  • 是的,它直接来自我的minecraft项目:)

    守则:

    Tools.isProcessExited()方法:

    Tools.restartMinecraft()方法:

    publicstaticvoidrestartminecraft(字符串args)抛出IOException、interruptedeexception{
    //在这里你可以做关机代码等
    进程p=Runtime.getRuntime().exec(args);
    RunnableWithObject inputStreamPrinter=新建RunnableWithObject(){
    @凌驾
    公开募捐{
    //TODO自动生成的方法存根
    当(!Tools.isProcessExit(数据))退出时{
    试一试{
    while(data.getInputStream().available()>0){
    System.out.print((char)data.getInputStream().read());
    }
    }捕获(IOE异常){
    }
    }
    }
    };
    RunnableWithObject errorStreamPrinter=新的RunnableWithObject(){
    @凌驾
    公开募捐{
    //TODO自动生成的方法存根
    当(!Tools.isProcessExit(数据))退出时{
    试一试{
    while(data.getErrorStream().available()>0){
    System.err.print((char)data.getErrorStream().read());
    }
    }捕获(IOE异常){
    }
    }
    }
    };
    inputStreamPrinter.data=p;
    errorStreamPrinter.data=p;
    新线程(inputStreamPrinter).start();
    新线程(errorStreamPrinter).start();
    p、 waitFor();
    System.out.println(“Minecraft已退出(“+p.exitValue()+”));
    System.exit(p.exitValue());
    }
    
    Tools.getCommandLineArgs()方法:

    公共静态字符串getCommandLineArgs(){
    字符串cmdline=“”;
    列表l=ManagementFactory.getRuntimeMXBean().getInputArguments();
    cmdline+=“java”;
    对于(int i=0;ipublic static boolean isProcessExited(Process p) {
        try {
            p.exitValue();
        } catch (IllegalThreadStateException e) {
            return false;
        }
        return true;
    }
    
        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());
        }
    
    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;
    }
    
    package generic.minecraft.infinityclient;
    
    public abstract class RunnableWithObject<T> implements Runnable {
        public T data;
    }