【发布时间】:2018-09-03 09:40:20
【问题描述】:
Java 9 为ObjectInputStreams 增加了一些反序列化安全措施,除了类的白名单/黑名单等更广泛使用的措施外,还增加了一些大小限制:arrayLength,depth, references, streamBytes.
数组的长度和深度很简单,但是如何正确使用references?文档说:The current number of object references,但是这些引用存储在哪里?它不是 InputStream 中当前的引用数。如果我通过流发送一个一次性使用实例并且不再需要它,我希望这个数字会再次下降,至少在它被垃圾收集时是这样。我意识到 ObjectStreams 维护一个HandleTable,默认情况下存储实例及其引用,但即使通过使用readUnshared/writeUnshared 来规避这一点,问题仍然存在。根据我的测试,我从未见过引用计数下降(streamBytes 也是如此)。
如果这个数字真的永远不会下降,您将如何处理不断发送数据的应用程序?即使您能够发送所有unshared 以便跟踪对象何时完成,您将如何确定该对象的streamBytes?
例子:
ObjectInputStream in; // e.g. get from a socket
in.setObjectInputFilter(new ObjectInputFilter() {
public Status checkInput(FilterInfo fi) {
if (fi.references() > 1000) return Status.REJECTED;
return Status.UNDECIDED;
}
});
【问题讨论】:
-
为什么数字会下降?
ObjectInputStream怎么知道你是否保留了这些物品?它是反序列化对象的简单计数器。要知道一个对象是否被垃圾回收,它必须为每个反序列化对象维护一个WeakReference,然后检查它们以获得该计数。如果不需要,那就太矫枉过正了,所以ObjectInputStream不会那样做,但也许这就是你需要自己做的。 -
从用户的角度来看,下降的数字会更有意义,因为否则你需要从一个下限开始并不断增加它,只要还有连续的数据流进来。据我所知,等待垃圾收集并没有真正起作用,因为所有对象都保存在 ObjectInputStream 的 HandleTable 中,因此永远不会被收集。可能有一种机制可以从 HandleTable 中释放对象,但它看起来不像,除了可能在流上使用 reset(),这还有其他复杂性。
-
其实
setObjectInputFilter的文档说“引用的数量是对象的累积个数,并且对已经从流中读取的对象的引用包括当前正在读取的对象”。我怀疑该功能是否适用于连续流媒体,因此下降的数字没有任何意义,而且肯定会违背记录的行为。
标签: java deserialization java-9