使用类加载器在java程序中运行可执行jar文件 [英] run a executable jar file within java program using class loaders

查看:462
本文介绍了使用类加载器在java程序中运行可执行jar文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我听说你可以使用Process或使用ClassLoaders来运行其他java文件。



我有一个名为<的主类的可执行jar'test.jar' code>测试。



我找到了一种使用Process运行的方法。我需要知道如何使用ClassLoaders。

 进程p = Runtime.getRuntime()。exec(java -jar Test.jar的); 
BufferedInputStream bis = new BufferedInputStream(p.getInputStream());
synchronized(p){
p.waitFor();
}
int b = 0;
while((b = bis.read())> 0){
System.out.print((char)b);
}


解决方案

基本方法是:




  • 创建类加载器,

  • 读取清单以查找入口点类

  • 加载入口点类,

  • 使用反射来获取其 public static void main(String [])方法,

  • 从新线程调用 main 方法,传递命令的命令行参数。



在这种特殊情况下的问题是设置System.in和System.out流,以便您可以与孩子交谈应用程序在同一个JVM中运行。问题是子应用程序期望System.out成为它将输出写入的流,并且父应用程序将从中读取。但是父应用程序期望System.out成为控制台(或其他)的输出流。这是行不通的,因为System.in/out/err是类字段,两个应用程序都不可避免地具有相同的值。



解决方案是改变父应用程序类的代码不使用System.in/out/err字段。在父级调用子级上的 main 方法之前,它必须使用 System.setOut(...)将其设置为将写入缓冲区的自定义输出流实例。然后你需要一个匹配的输入流实例,父可以从你的代码中读取...代替 bis



您需要解决的另一件事是子应用程序可能会调用 System.exit()。这会产生令人遗憾的影响,即插上父母的插件。



还有各种其他复杂情况,比如清理线程和其他东西。 。除非你的JVM实现了Isolates JSR(没有主流的JVM,AFAIK),否,有些事情你根本无法完全正确。除非您能够消除/避免这些问题,否则实现替代入口点和其他通信方式要简单得多。


I have heard that you could run other java files using Process or using ClassLoaders.

I have a executable jar 'test.jar' with a main class called Test.

I found a way to run using Process. I need to know how to do it using ClassLoaders.

Process p = Runtime.getRuntime().exec("java -jar test.jar");
BufferedInputStream bis = new BufferedInputStream(p.getInputStream());
synchronized (p) {
   p.waitFor();
}
int b=0;
while((b=bis.read()) >0){
   System.out.print((char)b);    
}

解决方案

The basic approach is to:

  • create the classloader,
  • read the manifest to find the entry point class
  • load the entry point class,
  • use reflection to get its public static void main(String[]) method, and
  • call the main method from a new thread, passing the command line arguments for the command.

The problem in this particular case is going to be in setting up the System.in and System.out streams so that you can talk to the "child application" running in the same JVM. The problem is that the "child application" expects System.out to be the stream that it writes it output to and that the "parent application" will read from. But the "parent application" expects System.out to be the output stream for the console (or whatever). And that won't work, because System.in/out/err are class fields that inevitably have the same value for both "applications".

The solution is to change the code of the parent application classes to not use the System.in/out/err fields. Before the "parent" calls the main method on the child, it must use System.setOut(...) to set it to a custom output stream instance that will write to a buffer. Then you need a matching input stream instance that the "parent" can read from ... in place of bis in your code.

Another thing you need to address is the possibility that the "child" application will call System.exit(). That will have the unfortunate effect of pulling the plug on the parent.

And there are all sorts of other complexities, like cleaning up threads and other stuff created by the "child". Some of these are basically unsolvable unless your JVM implements the Isolates JSR (which no mainstream JVMs do, AFAIK).

In short, doing this in the general case is really hard, and there are some things that you simply cannot get completely right. Unless you can eliminate / avoid these problems, it is much simpler to implement an alternative entrypoint, and alternative ways of communicating.

这篇关于使用类加载器在java程序中运行可执行jar文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆