2014-12-07 21 views
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文件,我不能确定,我不能编辑它。

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

+0

在单独的线程中产生该方法。 – engineerC 2014-12-07 04:44:06

+0

@CaptainMurphy在一个单独的线程中生成不会阻止显式调用jar文件中的System.exit()来终止JVM - 对于所有线程。 – 2014-12-07 04:44:49

+0

@christianhujer够公平的。如果这个jar坚持杀死jvm,你必须为每个调用产生一个新的jvm。在这种情况下,为什么不只是一个bash脚本。 – engineerC 2014-12-07 04:46:54

回答

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

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

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

两者都有优点和缺点。如果jar文件混淆了系统属性,那么您可能想要为单独的虚拟机寻求帮助,如果他们不这样做,那么您可能需要去安全管理器,因为这会降低开销。

1

最简单的方法不是从Java而是从shell脚本(或perl/python/ruby​​脚本)启动虚拟机多次。

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

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

+0

我宁愿用Python工作,你能推荐一个资源,告诉我如何做到这一点?我将不得不确保我运行的任何类路径都包含数据文件夹,并使用Java中的运行配置完成此操作。 – 2014-12-07 04:52:55