0

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

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

让我们假设是这种情况;我将如何解决这个问题来做我想做的事?即在调用以退出结束后,我的外部循环方法继续并使用下一个参数再次调用该类。

4

3 回答 3

5

如果问题确实是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 实例中造成副作用,也不必担心尝试猜测如何消除副作用。

于 2014-12-07T04:47:23.860 回答
1

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

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

两者都有优点和缺点。如果 jar 文件与系统属性混淆,您可能想要使用单独的虚拟机,如果没有,您可能想要使用 SecurityManager,因为这样开销会更少。

于 2014-12-07T04:46:51.633 回答
1

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

Runtime.exec您也可以使用或从 Java 中执行此操作ProcessBuilder.start

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

于 2014-12-07T04:47:34.777 回答