Как я могу запустить "main" в новом процессе на Java?
вопрос довольно простой. Как я могу запустить основной метод в другом процессе java? Теперь я делаю это так:
startOptions = new String[] {"java", "-jar", "serverstart.jar"};
new ProcessBuilder(startOptions).start();
но они попросили меня сделать это не с внешнего .файл jar. В serverstart.jar, очевидно, имеет основной метод ,но его можно вызвать в другом процессе, не вызывая.jar-файл?
Я думаю о чем-то вроде этого:
new ProcessBuilder(ServerStart.main(startOptions)).start();
но я не знаю, если что-нибудь подобное существует.
С уважением,
4 ответов
предполагая, что нового потока с новым загрузчиком классов недостаточно (я бы проголосовал за это решение), я понимаю, что вам нужно создать отдельный процесс, который вызывает основной метод в классе, не объявляя его как "основной метод jar" в файле манифеста-так как у вас нет отдельного serverstart.банку больше нет.
в этом случае, вы можете просто позвонить java -cp $yourClassPath your.package.ServerStart
, как и для запуска любого приложения java, когда у вас нет (или не хотите использовать) манифест основной класс.
создание нового процесса "java" из java-это не возможно, поскольку два процесса не могут совместно использовать один JVM. (См. вопрос и принял ответ).
если вы можете жить с создания нового Thread
вместо Process
вы можете сделать это с пользовательским ClassLoader
. Это как закрыть вы можете перейти к новому процессу. Все статические и конечные поля будут повторно инициализированы!
также обратите внимание, что "ServerStart
класс (для примера ниже) должен находиться в пути к классу текущей выполняющейся 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);
}
}
}
Я бы предложил вызвать shellscript из java и использовать его для запуска нового процесса (если вы вообще не можете жить с другим потоком).
вы можете сделать это с помощью отражения (java.ленг.отразить пакет).
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);
}