【问题标题】:How to use Java 9 ObjectInputFilter size constraints?如何使用 Java 9 ObjectInputFilter 大小限制?
【发布时间】: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


【解决方案1】:

如问题中所述,ObjectInputStream 维护对读取对象的引用(通过readUnshared、通过合适的serialPersistentFields 或类似的对象除外)。流中到目前为止未读取的数据可能对这些对象中的任何一个有反向引用(即使不存在其他引用,所以WeakReference 是一个红鲱鱼)。

没有重置的连续流对象泄漏。

我猜想尝试缓解的选项是使用少量数据创建大量对象的流,尽管我猜数据大小之间存在一个合理的ish线性因子和对象的数量(除非发生特殊情况)。

【讨论】:

    猜你喜欢
    • 2021-01-01
    • 2014-09-07
    • 1970-01-01
    • 2016-09-15
    • 1970-01-01
    • 1970-01-01
    • 2011-01-19
    • 1970-01-01
    相关资源
    最近更新 更多