Выполнение приложения Java в отдельном процессе

Может ли приложение Java загружаться в отдельный процесс, используя его имя, в отличие от его местоположения, независимо от платформы?

Я знаю, что вы можете выполнить программу через …

Process process = Runtime.getRuntime().exec( COMMAND ); 

… Основная проблема этого метода заключается в том, что такие вызовы являются специфическими для платформы.

В идеале, я бы обернул метод во что-то простое …

 EXECUTE.application( CLASS_TO_BE_EXECUTED ); 

… и передать полное имя classа приложения как CLASS_TO_BE_EXECUTED .

Два намека:

System.getProperty("java.home") + "/bin/java" дает вам путь к исполняемому файлу java.

((URLClassLoader() Thread.currentThread().getContextClassLoader()).getURL() помогает вам восстановить ((URLClassLoader() Thread.currentThread().getContextClassLoader()).getURL() текущего приложения.

Тогда ваш EXECUTE.application будет просто (псевдокод):

Process.exec(javaExecutable, "-classpath", urls.join(":"), CLASS_TO_BE_EXECUTED)

Это синтез некоторых других ответов, которые были предоставлены. Свойства системы Java предоставляют достаточную информацию, чтобы найти путь к команде java и classpath в том, что, я думаю, является независимым от платформы способом.

 public final class JavaProcess { private JavaProcess() {} public static int exec(Class klass) throws IOException, InterruptedException { String javaHome = System.getProperty("java.home"); String javaBin = javaHome + File.separator + "bin" + File.separator + "java"; String classpath = System.getProperty("java.class.path"); String className = klass.getCanonicalName(); ProcessBuilder builder = new ProcessBuilder( javaBin, "-cp", classpath, className); Process process = builder.start(); process.waitFor(); return process.exitValue(); } } 

Вы бы запускали этот метод следующим образом:

 int status = JavaProcess.exec(MyClass.class); 

Я подумал, что имеет смысл передавать в фактическом classе, а не в строковое представление имени, так как class должен быть в пути к classам, чтобы это работало.

Развернувшись на ответе @ stepancheg, фактический код будет выглядеть так (в форме теста).

 import org.junit.Test; import java.io.File; import java.net.URL; import java.net.URLClassLoader; import java.util.Arrays; import java.util.stream.Collectors; public class SpinningUpAJvmTest { @Test public void shouldRunAJvm() throws Exception { String classpath = Arrays.stream(((URLClassLoader) Thread.currentThread().getContextClassLoader()).getURLs()) .map(URL::getFile) .collect(Collectors.joining(File.pathSeparator)); Process process = new ProcessBuilder( System.getProperty("java.home") + "/bin/java", "-classpath", classpath, MyMainClass.class.getCanonicalName() // main class arguments go here ) .inheritIO() .start(); int exitCode = process.waitFor(); System.out.println("process stopped with exitCode " + exitCode); } } к import org.junit.Test; import java.io.File; import java.net.URL; import java.net.URLClassLoader; import java.util.Arrays; import java.util.stream.Collectors; public class SpinningUpAJvmTest { @Test public void shouldRunAJvm() throws Exception { String classpath = Arrays.stream(((URLClassLoader) Thread.currentThread().getContextClassLoader()).getURLs()) .map(URL::getFile) .collect(Collectors.joining(File.pathSeparator)); Process process = new ProcessBuilder( System.getProperty("java.home") + "/bin/java", "-classpath", classpath, MyMainClass.class.getCanonicalName() // main class arguments go here ) .inheritIO() .start(); int exitCode = process.waitFor(); System.out.println("process stopped with exitCode " + exitCode); } } 

Это может быть излишним для вас, но Project Akuma делает то, что вы хотите, и многое другое. Я нашел его через эту запись в Kohsuke’s (один из программистов Rock Rock), сказочно полезный блог.

Вы проверили API ProcessBuilder? Он доступен с 1,5

http://java.sun.com/javase/6/docs/api/java/lang/ProcessBuilder.html

Вам действительно нужно запускать их изначально? Не могли бы вы просто назвать их «основные» методы напрямую? Единственное особенное в главном состоит в том, что пусковая установка VM называет это, ничто не мешает вам самому называть себя.

 public abstract class EXECUTE { private EXECUTE() { /* Procedural Abstract */ } public static Process application( final String CLASS_TO_BE_EXECUTED ) { final String EXEC_ARGUMENT = new StringBuilder(). append( java.lang.System.getProperty( "java.home" ) ). append( java.io.File.separator ). append( "bin" ). append( java.io.File.separator ). append( "java" ). append( " " ). append( new java.io.File( "." ).getAbsolutePath() ). append( java.io.File.separator ). append( CLASS_TO_BE_EXECUTED ). toString(); try { return Runtime.getRuntime().exec( EXEC_ARGUMENT ); } catch ( final Exception EXCEPTION ) { System.err.println( EXCEPTION.getStackTrace() ); } return null; } } 

Следуя тому, что TofuBeer должен был сказать: вы уверены, что вам действительно нужно открутить другую JVM? В наши дни JVM действительно поддерживает параллелизм, поэтому вы можете получить много функциональности относительно дешево, просто открутив новую тему или две (которые могут или не требуют вызова в Foo # main (String [])). За дополнительной информацией обратитесь к java.util.concurrent.

Если вы решите развиваться, вы настроились на сложность, связанную с поиском необходимых ресурсов. То есть, если ваше приложение часто меняется и зависит от кучи файлов jar, вам нужно будет отслеживать их все, чтобы они могли быть переданы в argpath classов. Кроме того, такой подход требует вывода как местоположения (в настоящее время исполняемого) JVM (что может быть неточным), так и местоположения текущего пути к classам (что еще менее вероятно, будет точным, в зависимости от того, как нерестится Был вызван stream – jar, jnlp, exploded .classes dir, некоторый контейнер и т. Д.).

С другой стороны, привязка к статическим методам #main также имеет свои недостатки. статические модификаторы имеют неприятную склонность к утечке в другой код и, как правило, недовольны дизайнерами.

Проблема, возникающая, когда вы запускаете это из графического интерфейса java, выполняется в фоновом режиме. Таким образом, вы не видите командную строку.

Чтобы обойти это, вам нужно запустить java.exe через «cmd.exe» и «start». Я не знаю почему, но если вы поместите «cmd / c start» infront, он покажет командную строку при ее запуске.

Однако проблема с «стартом» заключается в том, что если в пути к приложению есть пробел (который путь к java exe обычно имеет, как и в C: \ Program Files \ Java \ jre6 \ bin \ java.exe или аналогичный), тогда начало просто терпит неудачу с «не может найти c: \ Program»

Таким образом, вы должны ставить кавычки в C: \ Program Files \ Java \ jre6 \ bin \ java.exe. Теперь начните жаловаться на параметры, которые вы передаете java.exe: «Система не может найти файл -cp.»

Выйти из пространства в «Program Files» с обратным слэшем также не работает. Поэтому идея состоит в том, чтобы не использовать пространство. Создайте временный файл с расширением bat, а затем введите команду с пробелами и запустите bat. Тем не менее, запуск летучей мыши через старт, не завершается, поэтому вы должны поместить «exit» в конец командного файла.

Это все еще кажется yucky.

Итак, ища альтернативы, я обнаружил, что использование цитаты цитаты цитаты в пространстве «Program Files» действительно работает с запуском.

В classе EXECUTE выше измените построитель строк, добавив:

 append( "cmd /C start \"Some title\" " ). append( java.lang.System.getProperty( "java.home" ).replaceAll(" ", "\" \"") ). append( java.io.File.separator ). append( "bin" ). append( java.io.File.separator ). append( "java" ). append( " " ). append( new java.io.File( "." ).getAbsolutePath() ). append( java.io.File.separator ). append( CLASS_TO_BE_EXECUTED ). 
  • Windows 7 - Высокая загрузка процессора во время простоя
  • получить имя процесса из идентификатора процесса (win32)
  • Приложение Windows Forms, такое как Google Chrome с несколькими процессами
  • popen () альтернатива
  • Перенаправление с помощью Runtime.getRuntime (). Exec () не работает
  • Как выполнить процесс на удаленном компьютере, в C #
  • Остановите запущенный процесс запуска на OS X Leopard
  • Как узнать, какие процессы обращаются к жесткому диску в системе на основе GNU / Linux?
  • Система и прерывания, вызывающие высокий CPU
  • как изменить имя процесса приложения Java?
  • Есть ли один JVM для Java-приложения?
  • Давайте будем гением компьютера.