在java下运行的软件_在单独的过程中执行Java应用程序

在单独的过程中执行Java应用程序

是否可以以与平台无关的方式使用Java应用程序的名称(而不是其位置)在单独的进程中加载Java应用程序?

我知道你可以通过...执行程序

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

...这种方法的主要问题是,此类调用是特定于平台的。

理想情况下,我会将方法包装成像...这样简单的东西。

EXECUTE.application( CLASS_TO_BE_EXECUTED );

...,并以CLASS_TO_BE_EXECUTED输入应用程序类的完全限定名称。

9个解决方案

66 votes

这是已提供的其他一些答案的综合。 Java系统属性提供了足够的信息,以我认为是平台独立的方式提供了java命令的路径和类路径。

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.getName();

ProcessBuilder builder = new ProcessBuilder(

javaBin, "-cp", classpath, className);

Process process = builder.inheritIO().start();

process.waitFor();

return process.exitValue();

}

}

您可以这样运行此方法:

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

我认为传递实际的类而不是名称的String表示形式是有意义的,因为无论如何该类都必须位于类路径中。

hallidave answered 2020-07-29T14:02:08Z

42 votes

两个提示:

Process.exec(javaExecutable, "-classpath", urls.join(":"), CLASS_TO_BE_EXECUTED)提供了Java可执行文件的路径。

Process.exec(javaExecutable, "-classpath", urls.join(":"), CLASS_TO_BE_EXECUTED)帮助您重构当前应用程序的类路径。

那么您的Process.exec(javaExecutable, "-classpath", urls.join(":"), CLASS_TO_BE_EXECUTED)就是(伪代码):

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

stepancheg answered 2020-07-29T14:01:39Z

6 votes

扩展@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.getName()

// main class arguments go here

)

.inheritIO()

.start();

int exitCode = process.waitFor();

System.out.println("process stopped with exitCode " + exitCode);

}

}

andrej answered 2020-07-29T14:02:28Z

4 votes

这对您来说可能是一个过大的杀伤力,但是Akuma项目可以满足您的需求甚至更多。我是在Kohsuke(Sun的摇滚入门程序员之一)的这篇博客中找到这篇文章的,它非常有用。

StaxMan answered 2020-07-29T14:02:48Z

3 votes

您是否签出了ProcessBuilder API? 从1.5开始可用

[HTTP://Java.孙.com/Java色/6/docs/API/Java/狼/process builder.HTML]

lothar answered 2020-07-29T14:03:13Z

3 votes

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;

}

}

Ande answered 2020-07-29T14:03:28Z

3 votes

您真的必须在本地启动它们吗? 您可以直接调用它们的“主要”方法吗? 关于main的唯一特殊之处是VM启动器会调用它,没有什么可以阻止您自己调用main的。

TofuBeer answered 2020-07-29T14:03:48Z

2 votes

遵循TofuBeer所说的话:您确定真的需要派遣另一个JVM吗? 如今,JVM确实对并发性提供了很好的支持,因此,只需拆分一个或两个新线程即可(不需调用Foo#main(String [])即可获得相对便宜的大量功能)。 查看java.util.concurrent以获取更多信息。

如果您决定分叉,则需要为查找所需资源付出一些复杂性。 也就是说,如果您的应用程序经常更改并且依赖于一堆jar文件,则您需要跟踪所有这些文件,以便将它们传递到类路径arg。 此外,这种方法需要推断(当前正在执行的)JVM的位置(可能不准确)和当前类路径的位置(甚至不太可能准确),具体取决于生成的方式 线程已被调用-jar,jnlp,分解的.classes目录,某些容器等)。

另一方面,链接到静态#main方法也有其陷阱。 静态修饰符有泄漏到其他代码中的讨厌趋势,并且通常被具有设计意识的人所反对。

jasonnerothin answered 2020-07-29T14:04:19Z

1 votes

从Java GUI运行此程序时发生的问题是它在后台运行。因此,您根本看不到命令提示符。

要解决此问题,您必须通过“ cmd.exe”和“ start”运行java.exe。我不知道为什么,但是如果在前面放置“ cmd / c start”,它将在运行时显示命令提示符。

但是,“启动”的问题是,到应用程序的路径中是否有空格(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扩展名的临时文件,然后在其中放置空格的命令并击球。但是,从开始运行蝙蝠,完成后不会退出,因此您必须在批处理文件的末尾添加“退出”。

这似乎仍然令人讨厌。

因此,在寻找替代方案时,我发现在“ Program Files”空间中使用引号空间quote实际上可以与start一起使用。

在上面的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 ).

Matiaan answered 2020-07-29T14:05:11Z

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值