问题很简单。如何在另一个java进程中启动main方法?现在我这样做:
startOptions = new String[] {"java", "-jar", "serverstart.jar"};
new ProcessBuilder(startOptions).start();
但他们要求我不要使用外部.jar文件。 serverstart.jar显然有一个main方法,但是可以在不调用.jar文件的情况下在另一个进程中调用该main方法吗?
我在考虑这样的事情:
new ProcessBuilder(ServerStart.main(startOptions)).start();
但我不知道是否存在类似的东西。
亲切的问候,
假设一个带有新类加载器的新线程是不够的(我会投票支持这个解决方案),我知道你需要创建一个独特的进程来调用类中的main方法,而不必在其中声明为“jar main方法”。清单文件 - 因为您不再具有不同的serverstart.jar。
在这种情况下,您只需致电 java -cp $yourClassPath your.package.ServerStart
,就像你没有(或不想使用)清单Main-Class时运行任何java应用程序一样。
从java创建一个新的“java”进程是 不 可能以后 两个进程无法共享一个JVM。 (见这个 问题和接受的答案)。
如果你能够创造一个新的 Thread
代替 Process
你可以用自定义做 ClassLoader
。就是这样 关闭你可以进入一个新的过程。所有静态和最终字段都将重新初始化!
还要注意 "ServerStart
class(以下示例)必须位于当前执行JVM的类路径中:
public static void main(String args[]) throws Exception {
// start the server
start("ServerStart", "arg1", "arg2");
}
private static void start(final String classToStart, final String... args) {
// start a new thread
new Thread(new Runnable() {
public void run() {
try {
// create the custom class loader
ClassLoader cl = new CustomClassLoader();
// load the class
Class<?> clazz = cl.loadClass(classToStart);
// get the main method
Method main = clazz.getMethod("main", args.getClass());
// and invoke it
main.invoke(null, (Object) args);
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
}
这是自定义类加载器:
private static class CustomClassLoader extends URLClassLoader {
public CustomClassLoader() {
super(new URL[0]);
}
protected java.lang.Class<?> findClass(String name)
throws ClassNotFoundException {
try{
String c = name.replace('.', File.separatorChar) +".class";
URL u = ClassLoader.getSystemResource(c);
String classPath = ((String) u.getFile()).substring(1);
File f = new File(classPath);
FileInputStream fis = new FileInputStream(f);
DataInputStream dis = new DataInputStream(fis);
byte buff[] = new byte[(int) f.length()];
dis.readFully(buff);
dis.close();
return defineClass(name, buff, 0, buff.length, (CodeSource) null);
} catch(Exception e){
throw new ClassNotFoundException(e.getMessage(), e);
}
}
}
我建议从java调用一个shellcript并使用它来启动新进程(如果你不能只使用另一个线程)。
您可以使用Reflection(java.lang.reflect包)执行此操作。
public static void main(String[] args) throws Exception {
Class c = Class.forName("ServerStart");
Class[] argTypes = { args.getClass() };
Method m = c.getMethod("main", argTypes);
Object passedArgv[] = { args };
m.invoke(null, passedArgv);
}