java - 是否可以从不同的 JVM 调用 Java 应用程序中的方法?

标签 java jvm init ubuntu-12.04

当我第一次使用 Apache 守护进程为 Windows 开发 Java 服务时,我使用了我非常喜欢的 JVM 模式。您指定您的类和开始\停止(静态)方法。但是对于 Linux,Jsvc 看起来没有相同的选项。我真的很想知道为什么?!

无论如何,如果我要使用 Linux 的 init 系统,我会尝试找到一种类似的方法来完成相同的行为,即以任何方式启动应用程序但要停止它,我将不得不调用一个方法在类里面。

我的问题是,在 jar 启动后,我如何使用 JVM 库或其他任何东西来调用我的应用程序中的方法(这将尝试优雅地停止我的应用程序)。

另一个问题,如果启动了一个应用程序并且该应用程序具有静态方法,如果我使用 java 命令行在一个应用程序中运行 main 方法类和 main 方法,它是 static 会调用类中的另一个静态方法,我想在其中发出终止信号,该调用会在同一个虚拟机?

最佳答案

为什么不向您的应用程序添加一个 ShutdownHook 呢?

A shutdown hook is simply an initialized but unstarted thread. When the virtual machine begins its shutdown sequence it will start all registered shutdown hooks in some unspecified order and let them run concurrently. When all the hooks have finished it will then run all uninvoked finalizers if finalization-on-exit has been enabled. Finally, the virtual machine will halt. Note that daemon threads will continue to run during the shutdown sequence, as will non-daemon threads if shutdown was initiated by invoking the exit method.

这将允许您的 jar 在关闭之前正常终止:

public class ShutdownHookDemo {
    public void start() {
        System.out.println("Demo");
        ShutdownHook shutdownHook = new ShutdownHook();
        Runtime.getRuntime().addShutdownHook(shutdownHook);
    }

    public static void main(String[] args) {
        ShutdownHookDemo demo = new ShutdownHookDemo();
        demo.start();
        try {
            System.in.read();
        }
        catch(Exception e) {
        }
    }
}

class ShutdownHook extends Thread {
    public void run() {
        System.out.println("Shutting down");
        //terminate all other stuff for the application before it exits
    }

}

注意事项

关闭 Hook 在以下情况下运行:

  • 程序正常存在。例如调用System.exit(),或者最后一个非守护线程退出。
  • 虚拟机已终止。例如CTRL-C。这对应于 kill -SIGTERM pid 或
  • 在 Unix 系统上 kill -15 pid。

关闭 Hook 在以下情况下不会运行:

  • 虚拟机中止
  • SIGKILL 信号被发送到 Unix 系统上的虚拟机进程。例如kill -SIGKILL pid 或 kill -9 pid
  • TerminateProcess 调用被发送到 Windows 系统上的进程。

或者,如果必须,您可以使用它来调用类中的方法:

public class ReflectionDemo {

  public void print(String str, int value) {
    System.out.println(str);
    System.out.println(value);
  }

  public static int getNumber() { return 42; }

  public static void main(String[] args) throws Exception {
    Class<?> clazz = ReflectionDemo.class;//class name goes here
    // static call
    Method getNumber = clazz.getMethod("getNumber");
    int i = (Integer) getNumber.invoke(null /* static */);
    // instance call
    Constructor<?> ctor = clazz.getConstructor();
    Object instance = ctor.newInstance();
    Method print = clazz.getMethod("print", String.class, Integer.TYPE);
    print.invoke(instance, "Hello, World!", i);
  }
}

动态加载一个类:

ClassLoader loader = URLClassLoader.newInstance(
    new URL[] { yourURL },
    getClass().getClassLoader()
);
Class<?> clazz = Class.forName("mypackage.MyClass", true, loader);
Class<? extends Runnable> runClass = clazz.asSubclass(Runnable.class);

引用资料:

关于java - 是否可以从不同的 JVM 调用 Java 应用程序中的方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11810627/

相关文章:

java - "Variable might not have been initialized"错误

swift - 属性初始值设定项在 'self' 可用之前运行

python - 从对象内部调用 __init__() 的效果

java - HttpEntity的consumeContent()的使用

java - 如果我从文件中读取一个大字符串,JVM 实际上会做什么?

java - 在浏览器中运行java-applet源代码

bash - 使用RHEL的 `daemon` init.d函数时,如何抓取PID?

java - assert(false) 不会停止执行

java - 可以将具有推断类型的局部变量重新分配给不同的类型吗?

java - 当我们有主题和属性时,如何在不使用 sparql 的情况下使用 jena 检索 RDF 中对象的值?