You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Apache Ignite对象反序列化失败问题求助

Tomcat + Ignite 运行一段时间后出现 SequenceEditableList 反序列化失败(filter status: REJECTED)

环境

  • Tomcat 8
  • Ignite 2.11.1
  • JDK 11 (Corretto)

问题描述

在Tomcat 8上运行一段时间后,使用Ignite存储HTTP会话的Web应用持续触发同一类型的反序列化错误,但应用启动初期运行正常。
SequenceEditableList 类继承自 ArrayList<>

错误日志

Caused by: org.apache.ignite.IgniteCheckedException: Failed to deserialize object with given class loader: [clsLdr=ParallelWebappClassLoader
  context: xxxxxx
  delegate: false
----------> Parent Classloader:
java.net.URLClassLoader@4277127c
, err=Failed to deserialize object [typeName=com.xxxx.web.common.list.SequenceEditableList]]
        at org.apache.ignite.internal.marshaller.optimized.OptimizedMarshaller.unmarshal0(OptimizedMarshaller.java:261)
        at org.apache.ignite.internal.marshaller.optimized.OptimizedMarshaller.unmarshal0(OptimizedMarshaller.java:225)
        at org.apache.ignite.marshaller.AbstractNodeNameAwareMarshaller.unmarshal(AbstractNodeNameAwareMarshaller.java:92)
        at org.apache.ignite.internal.binary.BinaryUtils.doReadOptimized(BinaryUtils.java:1816)
        ... 137 common frames omitted
Caused by: java.io.IOException: Failed to deserialize object [typeName=com.xxxx.web.common.list.SequenceEditableList]
        at org.apache.ignite.internal.marshaller.optimized.OptimizedObjectInputStream.readObject0(OptimizedObjectInputStream.java:357)
        at org.apache.ignite.internal.marshaller.optimized.OptimizedObjectInputStream.readObjectOverride(OptimizedObjectInputStream.java:205)
        at java.base/java.io.ObjectInputStream.readObject(ObjectInputStream.java:484)
        at java.base/java.io.ObjectInputStream.readObject(ObjectInputStream.java:451)
        at org.apache.ignite.internal.marshaller.optimized.OptimizedMarshaller.unmarshal0(OptimizedMarshaller.java:251)
        ... 140 common frames omitted
Caused by: java.io.IOException: java.lang.reflect.InvocationTargetException
        at org.apache.ignite.internal.marshaller.optimized.OptimizedObjectInputStream.readSerializable(OptimizedObjectInputStream.java:611)
        at org.apache.ignite.internal.marshaller.optimized.OptimizedClassDescriptor.read(OptimizedClassDescriptor.java:985)
        at org.apache.ignite.internal.marshaller.optimized.OptimizedObjectInputStream.readObject0(OptimizedObjectInputStream.java:353)
        ... 144 common frames omitted
Caused by: java.lang.reflect.InvocationTargetException: null
        at java.base/jdk.internal.reflect.GeneratedMethodAccessor169.invoke(Unknown Source)
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.base/java.lang.reflect.Method.invoke(Method.java:566)
        at org.apache.ignite.internal.marshaller.optimized.OptimizedObjectInputStream.readSerializable(OptimizedObjectInputStream.java:608)
        ... 146 common frames omitted
Caused by: java.io.InvalidClassException: filter status: REJECTED
        at java.base/java.io.ObjectInputStream.filterCheck(ObjectInputStream.java:1356)
        at java.base/java.io.ObjectInputStream.checkArray(ObjectInputStream.java:1386)
        at java.base/java.util.ArrayList.readObject(ArrayList.java:924)
        ... 150 common frames omitted

问题根因

错误栈最底层的java.io.InvalidClassException: filter status: REJECTED是核心原因,这是JDK 9+引入的**序列化过滤机制(JEP 290)**触发的拒绝行为。结合场景分析:

  1. Tomcat Web应用的类加载器(ParallelWebappClassLoader)在运行过程中可能发生重新加载(比如热部署),导致Ignite中存储的旧会话对象对应的类版本与当前类加载器中的类不匹配,被序列化过滤器拒绝。
  2. Ignite的OptimizedMarshaller没有正确关联Web应用的类加载器,导致反序列化时使用的类加载器上下文不符合过滤器规则。
  3. JDK默认的序列化过滤规则限制了ArrayList子类的反序列化操作。

解决方案

1. 调整JDK序列化过滤器规则

通过JVM参数明确允许目标类的反序列化,根据安全需求选择合适的规则:

  • 允许指定类及依赖类:
-Djdk.serialFilter=com.xxxx.web.common.list.SequenceEditableList;java.util.ArrayList;*
  • 允许Web应用全量包及基础JDK类:
-Djdk.serialFilter=com.xxxx.**;java.util.**;java.lang.**

2. 配置Ignite使用Web应用类加载器

在Ignite初始化时,指定使用Web应用的上下文类加载器,确保序列化/反序列化时类加载器一致:

IgniteConfiguration cfg = new IgniteConfiguration();
OptimizedMarshaller marshaller = new OptimizedMarshaller();
// 使用当前Web应用的类加载器
marshaller.setClassLoader(Thread.currentThread().getContextClassLoader());
// 开启类加载器缓存,避免频繁创建
marshaller.setClassLoaderCacheEnabled(true);
cfg.setMarshaller(marshaller);
Ignite ignite = Ignition.start(cfg);

如果使用XML配置:

<bean class="org.apache.ignite.configuration.IgniteConfiguration">
    <property name="marshaller">
        <bean class="org.apache.ignite.internal.marshaller.optimized.OptimizedMarshaller">
            <property name="classLoader" value="#{T(Thread).currentThread().getContextClassLoader()}"/>
            <property name="classLoaderCacheEnabled" value="true"/>
        </bean>
    </property>
    <!-- 其他Ignite配置 -->
</bean>

3. 避免类加载器泄漏与热部署影响

如果应用存在热部署场景,确保Web应用停止时正确关闭Ignite实例,避免旧类加载器被持有:

public class IgniteSessionListener implements ServletContextListener {
    private Ignite igniteInstance;

    @Override
    public void contextInitialized(ServletContextEvent event) {
        // 初始化Ignite
        IgniteConfiguration cfg = new IgniteConfiguration();
        // ...配置项
        igniteInstance = Ignition.start(cfg);
    }

    @Override
    public void contextDestroyed(ServletContextEvent event) {
        if (igniteInstance != null && !igniteInstance.isClosed()) {
            igniteInstance.close();
        }
    }
}

同时,建议在生产环境禁用Tomcat热部署,减少类加载器变更带来的问题。

4. 自定义序列化逻辑

为SequenceEditableList添加自定义序列化方法,绕过ArrayList默认的序列化流程,避免触发过滤器检查:

public class SequenceEditableList<T> extends ArrayList<T> {
    // 原有业务代码...

    private void writeObject(ObjectOutputStream out) throws IOException {
        out.defaultWriteObject();
        // 手动写入集合大小和元素
        out.writeInt(this.size());
        for (T element : this) {
            out.writeObject(element);
        }
    }

    private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
        in.defaultReadObject();
        int size = in.readInt();
        this.ensureCapacity(size);
        // 手动读取元素
        for (int i = 0; i < size; i++) {
            this.add((T) in.readObject());
        }
    }
}

内容的提问来源于stack exchange,提问作者Mr_Thorynque

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 02:50:35