【问题标题】:Is it possible to call method within a Java application from a different JVM?是否可以从不同的 JVM 调用 Java 应用程序中的方法?
【发布时间】:2012-08-02 09:10:06
【问题描述】:

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

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

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

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

【问题讨论】:

    标签: java jvm init ubuntu-12.04


    【解决方案1】:

    为什么不将ShutdownHook 添加到您的应用程序中呢?

    关闭挂钩只是一个已初始化但未启动的线程。什么时候 虚拟机开始其关闭顺序,它将全部启动 以某种未指定的顺序注册关闭挂钩并让它们运行 同时。当所有钩子都完成后,它将运行所有 如果 finalization-on-exit 已启用,则未调用的终结器。 最后,虚拟机将停止。请注意,守护线程将 在关闭序列期间继续运行,非守护进程也将继续运行 如果关闭是通过调用 exit 方法启动的,则线程。

    这将允许您的 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
        }
    
    }
    

    重要的是要注意

    关闭挂钩在以下情况下运行:

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

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

    • 虚拟机中止
    • 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);
    

    参考资料:

    【讨论】:

      【解决方案2】:

      基本上,在 JVM 之间调用的唯一方法是通过使用 Sockets,直接或通过基于它的实现,例如 RMI

      您可能会撒谎以查看http://www.javaworld.com/javaqa/2000-03/03-qa-0324-ipc.html 以获取更多信息

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-06-19
        • 1970-01-01
        • 1970-01-01
        • 2010-10-28
        • 2020-09-23
        • 1970-01-01
        相关资源
        最近更新 更多