[英]Java class loader independent from the system class loader for jar files
[英]How to get System out console from a jar loaded by a class loader?
我正在运行这样的外部jar插件:
Class<?> pluginClass = pluginLoader.loadClass(".......");
Method main = pluginClass.getMethod("main", String[].class);
main.invoke(null, new Object[] { new String[0] });
效果很好。 现在需要将插件控制台消息保存到字符串中
ByteArrayOutputStream baos = new ByteArrayOutputStream();
PrintStream ps = new PrintStream(baos); // how to indicate System.out coming from JAR plugin
System.setOut(ps);
// how to connect ps with plugin only
但是此代码将所有控制台消息保存到String中。 我不需要所有应用程序消息。 如何将仅插件消息重定向……此加载的jar中的消息到字符串中?
你不能做什么。 在此过程中,只有一个标准输出流,并且与插件代码和您的代码共享。
您可以将插件代码作为一个单独的过程运行,并捕获输出流。 您可以使用“ java.home”系统属性来找到启动您的进程的JRE的位置,并使用它来形成一个命令行来启动插件jar。
参见https://docs.oracle.com/javase/8/docs/api/java/lang/ProcessBuilder.html
System.out是针对每个进程的,每个类加载器都无法拥有不同的流。 如果您迫切需要从插件中取出系统,则有两种选择:1.如果您有权访问其代码,则将输出流传递给您的插件,并使插件使用此流。 2.将插件作为外部进程运行。 这样,您将能够重定向其输出。 另一个选择:如果您可以区分插件输出,则可以实现自己的路由输出流并将其设置为系统输出。
我做了这个解决方法:
public class CustomPrintStream extends PrintStream {
private String prefix;
public CustomPrintStream(String prefix, OutputStream out) {
super(out);
this.prefix = prefix;
}
@Override
public void println(String s) {
if(s.startsWith(prefix))
super.println(s);
else {
System.setOut(new PrintStream(new FileOutputStream(FileDescriptor.out)));
System.out.println(s);
System.setOut(this);
}
}
}
这使您可以为每个主程序的System.out.printlns添加一个前缀,以便它们可以正常执行。 没有前缀的插件(来自您的插件)直接进入已定义的输出流(在我的示例中为fileoutputstream)
它的用法如下:
System.setOut(new CustomPrintStream("test", new FileOutputStream("C:\\out.txt"))); //Of course you can also use ByteArrayOutputStream, as you did before
System.out.println("test 1"); //this goes into the standard outstream
System.out.println("2"); //and this goes into the fileoutputstream
System.out.println("test 3");
也许这会帮助您:)
编辑:我切换它,以便带有前缀的字符串进入正常的外流
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.