检测 Java 中 OutputStream 的目标 (File/Socket/etc) 的类型

Detect the type of the target (File/Socket/etc) of an OutputStream in Java

假设我传递了一个 OutputStream 变量。有什么方法可以检测 OutputStream 的源是打开的文件还是打开的套接字等?

如果不可能,如果我知道变量的类型是 FileOutputStream 是不是更好,这样我就可以得到它的 FileDescriptor。谢谢。


更新:

每个 FileOutputStream 实例都有一个 FileDescriptor。我无法区分它的来源,因为从 Java 文档:

文件描述符的实例class作为底层机器特定结构的不透明句柄,表示一个打开的文件、一个打开的套接字或另一个源或字节汇。文件描述符的主要实际用途是创建一个 FileInputStream 或 FileOutputStream 来包含它。


更新 2:

我正在开发一个构建在自定义 JVM 之上的自动化工具,用于分析 Java 字节码,并确定程序写入文件或通过套接字发送的字节数等(在非常简单的程序)。然后以不同方式处理文件、套接字等。

定制的JVM在执行字节码指令时让我知道INVOKEVIRTUAL,我可以检查被调用者是OutputStream。现在我需要做的是确定此 OutputStream 写入 File/Socket 等的位置

使用instanceof运算符是什么类型的对象。例如你可以检查

if(currentObject instanceof FileOutputStream){}

或者您可以使用

yourObject.getClass().getName()

想简单点,可以用instance of

if(myStream instanceof FileOutputStream){
    //this is FileOutputStream
}

但有些情况您无法检测到,例如 FileOutputStream 是否被另一个 OutputStream(如 FilterOutputStream)包装。所以,如果你的流的实例是 FilterOutputStream,你必须找到真正的内部。当流被包装时:

 public FilterOutputStream(OutputStream out) {
        this.out = out;
 }

但是,通过正常方式,我们无法将 this.out(受保护)再次发送到 运行 instance of。我考虑反射以获得受保护或私有字段(Java reflection - access protected field)

但是,如果内部流又是另一个 FilterOutputStream!!!你必须使用递归函数来检测。

想象一下 Java 中的 Stream 就像 Matroska 木偶一样!

这只是我的想法。如果你想完全控制它。你必须看到 Java IO

的树

由于您基本上是在对 write 的所有调用上设置断点,因此您需要检查方法调用的实际 class:

  • 如果它是 FilterOutputStream(其中一个是子class),请忽略它。包装流的 write 方法也会被调用。
  • 如果它是 java.net.SocketOutputStream(不是 public,FileOutputStream 的子class),你知道目标是一个套接字。
  • 如果是FileOutputStream(不是子class),私有字段path有用于打开流的文件路径。
  • 如果它是一个 ByteArrayOutputStream,你知道目标是一个内存缓冲区。
  • 如果是其他情况,你需要研究如何处理它,或者直接忽略。