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

时间:2014-12-07 04:39:44

标签: java securitymanager systemexit

我正在编写一个程序,我想循环遍历几个配置文件,并且每个文件都调用一个以该文件名作为参数的类,并等待它完成。目前我在做:

    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文件,我无法确定,我无法编辑它。

让我们假设是这样的;我该如何解决这个问题呢?即,在调用以exiting结束后,我的外部循环方法继续,并再次使用下一个参数调用该类。

3 个答案:

答案 0 :(得分:5)

如果问题确实是第三方课程中的System.exit()电话,您应该可以按照this answer中的建议解决问题,该建议提供以下代码:

  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 ) ;
  }

但是,出于您的目的,对于第三方应用程序简单spawn a separate Java process并等待它终止可能是更好的方法。这样您就不必担心第三方代码会导致JVM实例出现副作用,或者想要猜测如何摆脱副作用。

答案 1 :(得分:1)

我知道如何解决这个问题的两种可能性:

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

两者都有利弊。如果jar文件混乱了系统属性,你可能想要一个单独的VM,如果他们不这样做,你可能想要使用SecurityManager,因为这会减少开销。

答案 2 :(得分:1)

最简单的方法不是来自Java,而是来自shell脚本(或perl / python / ruby​​脚本),只需多次启动VM。

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

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