如何正确使用Java 9 ObjectInputFilter的references大小约束?
详解Java 9 ObjectInputStream中的
references安全约束 嘿,这个问题问到点子上了——Java 9给ObjectInputStream新增的几个反序列化安全限制里,references确实是最容易让人混淆的那个,我来给你拆解明白。
首先得搞清楚:references约束跟踪的对象引用,到底存在哪儿?
ObjectInputStream在反序列化过程中,会维护一个内部对象引用表。这个表的作用是记录已经成功反序列化的对象实例,用来处理对象的重复引用或者循环引用场景——比如反序列化一个对象A,它里面引用了对象B,之后再遇到对B的引用时,就直接从这个表里取出已有的实例,不用重新创建,这样既保证了对象引用的一致性,也避免了重复反序列化的开销。
那references约束到底管什么?
它限制的是这个内部引用表中能容纳的唯一对象的最大数量。一旦反序列化过程中,引用表的大小超过了你设置的阈值,JVM会直接抛出StreamCorruptedException,中断反序列化操作。这个约束主要是用来防范恶意序列化数据的攻击——比如攻击者构造一个包含大量重复/循环引用的序列化流,试图耗尽JVM内存,references就能在问题扩大前直接终止操作。
怎么正确使用references约束?
- 通过对象输入过滤器配置:你需要用
ObjectInputStream.setObjectInputFilter()方法来设置这个阈值,举个实际代码例子:
try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream("your-data.ser"))) { ois.setObjectInputFilter(filterInfo -> { // 限制引用表最多容纳1000个唯一对象 if (filterInfo.references() > 1000) { return ObjectInputFilter.Status.REJECTED; } // 可以同时搭配其他约束,比如数组长度、深度等 if (filterInfo.arrayLength() > 500) { return ObjectInputFilter.Status.REJECTED; } return ObjectInputFilter.Status.ALLOWED; }); Object deserializedObj = ois.readObject(); } catch (IOException | ClassNotFoundException e) { // 处理异常 }
- 根据业务场景设置合理阈值:如果你的序列化数据都是简单对象(比如单个实体类,没有复杂关联),设置几百的阈值就足够;如果是处理复杂的对象图(比如包含多层关联的业务对象、集合),可以适当调高,但别设得过大——毕竟安全约束的核心是防止资源耗尽,阈值太高就失去了防护意义。
- 注意计数规则:
references统计的是唯一对象的数量,同一个对象被多次引用不会重复计数。比如你反序列化一个List,里面100个元素都引用了同一个User对象,那引用表只会记录这个User一次,references的计数只会加1(加上List本身就是2)。
最后补充一句:你提到“它并非指当前……”,没错,references绝对不是指单个对象的引用数量,而是从反序列化开始到当前时刻,所有被加入引用表的全局唯一对象总数。
内容的提问来源于stack exchange,提问作者Caranown
相关产品推荐
相关产品推荐

