简体   繁体   English

如何从类加载器加载的jar中获取系统控制台?

[英]How to get System out console from a jar loaded by a class loader?

I am running an external jar plugin like this: 我正在运行这样的外部jar插件:

  Class<?> pluginClass = pluginLoader.loadClass(".......");     
  Method main = pluginClass.getMethod("main", String[].class);
  main.invoke(null, new Object[] { new String[0] }); 

It works great. 效果很好。 Now need to save the plugin console messages into a String 现在需要将插件控制台消息保存到字符串中

  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 

But this code saves ALL console messages into String. 但是此代码将所有控制台消息保存到String中。 I don't need all application messages. 我不需要所有应用程序消息。 How to redirect plugin only messages......messages coming from this loaded jar into the string? 如何将仅插件消息重定向……此加载的jar中的消息到字符串中?

You can't do what you are asking. 你不能做什么。 There is only one standard output stream in the process and it is shared with the plugin code and your code. 在此过程中,只有一个标准输出流,并且与插件代码和您的代码共享。

You could instead run the plugin code as a separate process and capture the output stream. 您可以将插件代码作为一个单独的过程运行,并捕获输出流。 You can use the "java.home" System Property to find the location of the JRE that launched your process and use that to form a command line to launch the plugin jar. 您可以使用“ java.home”系统属性来找到启动您的进程的JRE的位置,并使用它来形成一个命令行来启动插件jar。

See https://docs.oracle.com/javase/8/docs/api/java/lang/ProcessBuilder.html 参见https://docs.oracle.com/javase/8/docs/api/java/lang/ProcessBuilder.html

System.out is per process, no way to have different stream per class loader. System.out是针对每个进程的,每个类加载器都无法拥有不同的流。 If you desperately need to get the system out from plugin there are 2 options : 1. Pass output stream to your plugin if you have acces to its code and make plugin use this stream. 如果您迫切需要从插件中取出系统,则有两种选择:1.如果您有权访问其代码,则将输出流传递给您的插件,并使插件使用此流。 2. Run your plugin as external process. 2.将插件作为外部进程运行。 This way you will be able to redirect its output. 这样,您将能够重定向其输出。 Another option : if you can differentiate the plugins output, you can implement your own routing output stream and set it as system out. 另一个选择:如果您可以区分插件输出,则可以实现自己的路由输出流并将其设置为系统输出。

I made this workaround: 我做了这个解决方法:

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);
        }
    }
}

This offers you the possibility to add a prefix to each of you main program's System.out.printlns, so that they get executed normally. 这使您可以为每个主程序的System.out.printlns添加一个前缀,以便它们可以正常执行。 The ones without the prefix (from your plugin) get directly into the defined out-stream (in my example the fileoutputstream) 没有前缀的插件(来自您的插件)直接进入已定义的输出流(在我的示例中为fileoutputstream)

It is used like this: 它的用法如下:

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");

Maybe this will help you :) 也许这会帮助您:)

Edit: I switched it around so that the string with prefix goes into the normal outstream 编辑:我切换它,以便带有前缀的字符串进入正常的外流

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Java类加载器,独立于jar文件的系统类加载器 - Java class loader independent from the system class loader for jar files 如何获取从jar加载的,不在classpath中的任何类作为流? - How to get as a stream any class loaded from a jar not in the classpath? 在Jetty中使用系统类加载器加载外部jar - Load external jar with system class loader in Jetty 如何获取引导类加载器加载的所有类的列表? - How to get a list of all classes that are loaded by the bootstrap class loader? class 加载器是否可以获取已由不同 class 加载器加载的类? - Is it possible for class loader to get classes already loaded by different class loader? 如何获取 jar 的名称,JVM 在运行时从中加载 class - How to get name of jar from which class is loaded at runtime by JVM in Java 11 如何使加载的jar使用自身资源而不是加载器? - How can I make a loaded jar use resources from itself rather than its loader? Android内存泄漏,EMA可疑:“byte []”由“<system class loader>”加载 - Android Memory Leak, EMA Suspect: “byte[]” loaded by “<system class loader>” Java ClassLoader - 将动态加载的 jars 添加到系统 class 加载器 - Java ClassLoader - Adding dynamically loaded jars to the system class loader 如何为不同的jar版本分离类加载器? - How to separate class loader for different jar version?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM