检测 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
,你知道目标是一个内存缓冲区。
- 如果是其他情况,你需要研究如何处理它,或者直接忽略。
假设我传递了一个 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
,你知道目标是一个内存缓冲区。 - 如果是其他情况,你需要研究如何处理它,或者直接忽略。