IDE风格的程序正在运行

时间:2010-10-23 07:35:18

标签: java

我的目标


我正在尝试制作一个Java程序,用户可以从其计算机中选择任何.class.jar文件。然后,我的程序将弹出一个JInternalFrame,其中包含JEditorPane作为控制台,捕获用户程序的任何控制台输出。当用户的程序关闭(调用System.exit(int status);)时,我的程序不能随之关闭。我的程序可能还有一个功能,如立即停止用户程序的按钮和IDE的其他功能。我的程序不需要编译Java代码,只需运行.class.jar文件。

我的经历


我已经制作了这个程序的一个小测试版本,其中我从一个包中获得了两个特定文件,并让用户单击两个按钮中的一个,每个按钮代表两个程序中的一个。按一下按钮会调用以下方法:

  private void run(Class runnable)
  {
    java.lang.reflect.Method[] m = runnable.getMethods();
    boolean hasMain = false;
    for (int i = 0; i < m.length; i++)
    {
      if (m[i].getName().equals("main") && m[i].getParameterTypes()[0].isArray() && m[i].getParameterTypes()[0].getName().contains("java.lang.String"))
        try
        {
          Object invoke = m[i].invoke(null, (Object)globalArgs);
          hasMain = true;
          hub.setExtendedState(Hub.ICONIFIED);
          numPrograms++;
        }
        catch (Throwable t)
        {
          java.util.logging.Logger.getLogger(Hub.class.getName()).log(java.util.logging.Level.SEVERE, null, t);
          javax.swing.JOptionPane.showMessageDialog(null, "Could not run " + runnable.getName(), "Error in invocation", javax.swing.JOptionPane.ERROR_MESSAGE);
        }
        finally
        {
          break;
        }
    }
    if (!hasMain)
      javax.swing.JOptionPane.showMessageDialog(null, runnable.getName()
                                                      + " does not have a public static main method that\nreturns void and takes in an array of Strings",
                                                "No main method", javax.swing.JOptionPane.ERROR_MESSAGE);
  }

此方法成功调用程序的main方法并运行所述程序的副本。但是,当此集线器已启动的任何程序调用{​​{1}}命令时,集线器也会关闭。另外,我对如何捕获控制台输出没有丝毫的线索。

我的问题


是否有人有任何经验或建议,他们愿意分享这些经验或建议,以帮助我制作一个功能齐全的计划......

  1. 打开并运行已编译的Java文件(请记住,System.exit(int status)个文件可能包含多个具有.jar方法的类)
  2. Catch main(String[] args)以便中心程序处理内部程序退出
  3. 抓住System.exit(int status);和类似的来电并将其输出放在new java.io.PrintStream().println(Object o)
  4. 按下一个按钮,按下该按钮,停止内部程序运行
  5. 可能会将内部程序使用的所有JEditorPane都放入JFrame并将其放入JInternalFrame

1 个答案:

答案 0 :(得分:7)

如果您不希望其他程序(通过它的主方法调用)能够关闭您正在运行的JVM,那么我有三个选项:

1。使用SecurityManager

设置 SecurityManager ,以防止System.exit来电:

public class Test {
    public static void main(String args[]) {
        SecurityManager sm = System.getSecurityManager();
        System.setSecurityManager(new SecurityManager() {
            @Override
            public void checkExit(int status) {
                throw new SecurityException("Client program exited.");
            }
        });

        try {
            System.out.println("hello");
            System.exit(0);
            System.out.println("world");
        } catch (SecurityException se) {
            System.out.println(se.getMessage());
        }
    }
}

<强>打印

hello
Client program exited.

这可能是最好的解决方案。这是应用程序服务器阻止任意servlet终止整个服务器的方式。

2。单独的JVM

使用例如ProcessBuilder

在单独的JVM中运行其他程序
import java.io.*;

public class Test {
    public static void main(String args[]) throws IOException {

        ProcessBuilder pb = new ProcessBuilder("java", "other.Program");
        pb.redirectErrorStream();
        Process p = pb.start();
        InputStream is = p.getInputStream();
        int ch;
        while ((ch = is.read()) != -1)
            System.out.print((char) ch);
        is.close();
        System.out.println("Client program done.");
    }
}

3。改为使用关闭钩子

不要禁止终止JVM,而是添加关闭钩子来清理“集线器”并正常退出。 (如果你一次运行一个“外部”程序,这个选项可能才有意义。)

import java.io.*;

public class Test {

    public static void main(String args[]) throws IOException {

        Runtime.getRuntime().addShutdownHook(new Thread() {
            public void run() { 
                System.out.println("Uninitializing hub...");
                System.out.println("Exiting gracefully.");
            }
        });

        // Run client program
        System.out.println("Running... running... running...");
        System.exit(0);

     }
}

<强>打印

Running... running... running...
Uninitializing hub...
Exiting gracefully.