呼叫类,等待它退出,再次呼叫



我正在开发一个程序,我想循环访问多个配置文件,并且对于每个文件,调用一个具有该文件名的类作为参数并等待它完成。 目前我正在做:

    for (int i = 1; i <= 3; i++){
        String[] a = new String[1];
        a[0] = "data/config" + i + ".xml";
        edu.cwru.sepia.Main2.class.getMethod("main", String[].class).invoke(null, (Object)a);
    }

但是,发生的情况是该类只被调用一次,然后整个程序停止。 我认为类中有一条退出线,但由于它是一个 JAR 文件,我不能确定,也无法编辑它。

让我们假设是这样;我将如何绕过它来做我想做的事? 即在调用以退出结束之后,我的外部循环方法继续,只是使用下一个参数再次调用该类。

如果问题确实是第三方类中的System.exit()调用,您应该能够按照此答案中的建议来解决它,该答案提供了以下代码:

  private static class ExitTrappedException extends SecurityException { }
  private static void forbidSystemExitCall() {
    final SecurityManager securityManager = new SecurityManager() {
      public void checkPermission( Permission permission ) {
        if( "exitVM".equals( permission.getName() ) ) {
          throw new ExitTrappedException() ;
        }
      }
    } ;
    System.setSecurityManager( securityManager ) ;
  }
  private static void enableSystemExitCall() {
    System.setSecurityManager( null ) ;
  }
但是,出于

您的目的,简单地为第三方应用程序生成一个单独的 Java 进程并等待它终止可能是一种更好的方法。 这样,您就不必担心第三方代码会在 JVM 实例中引起副作用,也不必担心试图猜测如何摆脱副作用。

我知道有两种可能性可以解决这个问题:

  • 在调用此main()方法之前,可以安装实现 checkExit() 方法的SecurityManager。这将防止System.exit()实际发生。
  • 您可以在单独的 VM 中运行该方法,即使用Runtime.exec()方法之一启动它。

两者都有利有弊。如果jar文件弄乱了系统属性,您可能需要使用单独的VM,如果没有,则可能需要使用SecurityManager,因为这样可以减少开销。

最简单的方法不是从Java,而是从shell脚本(或perl/python/ruby脚本),然后多次启动VM。

您也可以使用 Runtime.execProcessBuilder.start 从 Java 执行此操作。

调用 JVM

时不停止 JVM 并不容易System.exit()。不过有一种方法可以做到这一点;通过使用System.setSecurityManager调用安装您自己的SecurityManager。然后,您可以重写 canExit 方法并抛出异常(或Error)子类。但是,除非您了解后果,否则不建议这样做,因为它会为整个JVM打开SecurityManager,这可能会产生意想不到的后果。

最新更新