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

时间:2012-08-04 17:33:54

标签: java jvm init ubuntu-12.04

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

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

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

另一个问题是,如果应用程序已启动并且该应用程序具有静态方法,那么如果我使用java命令行在一个应用程序类中运行main方法,那么{{ 1}}方法,main会在类中调用另一个静态方法,我想在其中发出终止信号的信号,是否会在同一个static中调用?

2 个答案:

答案 0 :(得分:8)

为什么不在您的应用中添加ShutdownHook

  

关闭钩子只是一个初始化但未启动的线程。什么时候   虚拟机开始关闭序列,它将启动所有   注册的shutdown挂钩以某种未指定的顺序挂起并让它们运行   同时。当所有钩子都完成后,它将全部运行   如果启用了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。

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

  • 虚拟机中止
  • 在Unix系统上将SIGKILL信号发送到虚拟机进程。例如杀死-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);

<强>参考文献:

答案 1 :(得分:2)

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

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