Запуск программы в стиле IDE - PullRequest
3 голосов
/ 23 октября 2010

Моя цель


Я пытаюсь создать программу на 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);
  }

Этот метод успешно вызывает основной метод любой программы и запускает копию указанной программы.Однако когда любая из программ, запущенных этим хабом, вызывает команду System.exit(int status), хаб тоже закрывается.Кроме того, я не имею ни малейшего понятия о том, как захватить вывод консоли.

Мои вопросы


У кого-нибудь есть опыт или совет, которым он хотел бы поделиться, чтобы помочь мнесоздать полнофункциональную программу, которая может ...

  1. Открыть и запустить скомпилированный файл Java (помните, что файлы .jar могут иметь более одного класса с методом main(String[] args))
  2. Catch System.exit(int status);, так что хаб-программа обрабатывает внутренние программы завершения
  3. Catch new java.io.PrintStream().println(Object o) и аналогичных вызовов и помещает их вывод в JEditorPane
  4. Сделайте кнопку, которая при нажатии останавливает выполнение внутренней программы
  5. Возможно, сделайте все JFrame с, которые внутренняя программа использует в JInternalFrame с, и поместите их в JDesktopPane

1 Ответ

7 голосов
/ 23 октября 2010

Если вы не хотите, чтобы другая программа (которую вы вызываете с помощью основного метода) могла отключить 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.

Это, наверное, самое хорошее решение. Именно так серверы приложений не позволяют произвольному сервлету завершить работу всего сервера.

2. Отдельная JVM

Запустите другую программу в отдельной JVM, используя, например, ProcessBuilder

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.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...