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

Java 8升级Java 17后JMeter序列化失败问题咨询

问题描述

项目从Java 8迁移至Java 17,原Java 8环境依赖如下:

<!-- Spring version -->
<spring.version>5.2.16.RELEASE</spring.version>
<spring.autoconfig.version>2.6.3</spring.autoconfig.version>
<!-- Jmeter version --> 
<jmeter.version>5.4.1</jmeter.version>

<dependency>
    <groupId>com.fasterxml.jackson.dataformat</groupId>
    <artifactId>jackson-dataformat-xml</artifactId>
    <version>2.9.9</version>
</dependency>
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-core</artifactId>
    <version>2.9.9</version>
</dependency>
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-annotations</artifactId>
    <version>2.9.9</version>
</dependency>
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.9.9</version>
</dependency>
<dependency>
    <groupId>org.apache.jmeter</groupId>
    <artifactId>ApacheJMeter_core</artifactId>
    <version>${jmeter.version}</version>
</dependency>
<dependency>
    <groupId>org.apache.jmeter</groupId>
    <artifactId>ApacheJMeter_java</artifactId>
    <version>${jmeter.version}</version>
    <exclusions>
        <exclusion>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
        </exclusion>
        <exclusion>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
        </exclusion>
    </exclusions>
</dependency>
<dependency>
    <groupId>org.apache.jmeter</groupId>
    <artifactId>ApacheJMeter_http</artifactId>
    <version>${jmeter.version}</version>
    <exclusions>
        <exclusion>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
        </exclusion>
        <exclusion>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
        </exclusion>
    </exclusions>
</dependency>

项目采用JMeter分布式测试架构,需将测试对象序列化后发送至远程JMeter引擎。

迁移至Java 17后,更新了Spring/JMeter版本(序列化库版本保持不变):

<spring.boot.version>3.0.2</spring.boot.version>
<spring.version>6.0.4</spring.version>
<jmeter.version>5.5</jmeter.version>

测试类继承自Spring的AbstractTestNGSpringContextTests,Java 8环境下可正常序列化,Java 17环境下序列化失败,报错信息如下:

Error in rconfigure() method java.rmi.MarshalException: error marshalling arguments; nested exception is: 
    java.io.NotSerializableException: org.springframework.context.support.GenericApplicationContext

AbstractTestNGSpringContextTests包含核心字段:

@Nullable
protected ApplicationContext applicationContext;

该字段是序列化失败的关键原因,但Java 8/Spring 5.2.16版本可正常运行,需明确问题成因及Spring新版本的可行解决方案。

问题成因
  1. Spring版本变更导致ApplicationContext实现类序列化特性改变
    Spring 5.x中,GenericApplicationContext通过继承链间接实现了Serializable接口,因此即使applicationContext字段未标记transient,也能完成序列化。但Spring 6.x(适配Java 17)对GenericApplicationContext的实现进行了调整,移除了Serializable接口的实现,导致该对象无法被Java默认序列化机制处理。

  2. Java序列化机制严格性提升
    Java 17对序列化的安全性和规范要求更严格,低版本中能“隐性”通过的非标准可序列化对象,在Java 17中会被明确抛出NotSerializableException,直接暴露了Spring版本变更带来的序列化兼容性问题。

可行解决方案

方案1:标记applicationContext为transient

在自定义测试类中重写applicationContext字段,添加transient关键字,让Java序列化机制跳过该字段的序列化:

import org.springframework.context.ApplicationContext;
import org.springframework.lang.Nullable;
import org.springframework.test.context.testng.AbstractTestNGSpringContextTests;

public class YourTestClass extends AbstractTestNGSpringContextTests {
    @Nullable
    protected transient ApplicationContext applicationContext;
}

说明:远程JMeter引擎不需要Spring上下文,跳过该字段序列化不影响分布式测试逻辑。

方案2:自定义序列化逻辑

如果测试类需要保留部分Spring上下文相关信息,可实现Serializable接口并自定义writeObject/readObject方法,手动控制序列化内容:

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import org.springframework.test.context.testng.AbstractTestNGSpringContextTests;

public class YourTestClass extends AbstractTestNGSpringContextTests implements Serializable {
    private void writeObject(ObjectOutputStream out) throws IOException {
        // 仅序列化测试逻辑需要的字段,跳过applicationContext
        out.defaultWriteObject();
    }

    private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
        in.defaultReadObject();
        // 反序列化时可根据需求重新初始化applicationContext
    }
}

方案3:重构测试类结构

将测试逻辑与Spring上下文解耦,拆分出独立的测试负载类用于JMeter分布式传输:

  • 创建JmeterTestPayload类,仅包含分布式测试需要的字段和逻辑,实现Serializable接口。
  • 原测试类仅保留Spring上下文初始化逻辑,构建JmeterTestPayload对象后发送给远程JMeter引擎。

方案4:替换序列化机制

放弃Java默认序列化,改用Jackson等序列化库对测试对象进行序列化/反序列化,发送字节流或JSON/XML数据给远程JMeter引擎,避免依赖Java默认序列化对Serializable接口的要求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 21:33:09