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

Java 21+Maven环境下JMeter测试日志保存及XStream报错解决

JDK 21环境下JMeter测试执行日志获取方案

报错原因说明

你遇到的错误确实是JDK 21的模块系统(JPMS)限制导致:XStream(JMetersaveTree()方法依赖的序列化库)需要反射访问java.util包的内部成员,但JDK 21默认不允许未命名模块访问这些受限包,因此序列化操作失败。

下面提供三种无需注释saveTree()或能替代获取测试详情的方案:

方案1:直接配置JMeter结果收集器输出日志文件

不用依赖saveTree(),直接通过ResultCollector组件生成标准JMeter结果文件(CSV/XML格式),步骤如下:

在你的测试代码中添加结果收集器:

import org.apache.jmeter.reporters.ResultCollector;
import org.apache.jmeter.reporters.Summariser;
import org.apache.jmeter.save.SaveService;
import org.apache.jorphan.collections.HashTree;

// 初始化JMeter配置、创建测试计划HashTree(保留你已有代码)
HashTree testPlanTree = ...;

// 添加CSV结果收集器
ResultCollector resultCollector = new ResultCollector(new Summariser());
resultCollector.setFilename("jmeter-test-results.csv"); // 指定输出文件路径
// 如果要XML格式,替换为以下两行:
// resultCollector.setFilename("jmeter-test-results.xml");
// resultCollector.setSaveConfig(SaveService.getXmlSaveConfig());

// 将结果收集器添加到测试树
testPlanTree.add(testPlanTree.getArray()[0], resultCollector);

// 执行测试(保留你已有代码)

测试完成后,直接打开生成的CSV/XML文件即可查看请求响应时间、状态码、响应大小等所有测试详情。

方案2:添加JVM参数开放模块权限,恢复saveTree()功能

如果必须保留saveTree(),可以在启动Java程序时添加以下JVM参数,解除JDK模块对XStream的访问限制:

--add-opens java.base/java.util=ALL-UNNAMED
--add-opens java.base/java.util.concurrent=ALL-UNNAMED
--add-opens java.base/java.io=ALL-UNNAMED
  • IDE环境:在Run Configuration的VM Options中添加上述参数
  • 命令行运行:在java -jar或javac命令前加上这些参数

添加后,saveTree()就能正常序列化测试树,同时你依然可以配置ResultCollector生成测试详情日志。

方案3:自定义样本监听器收集测试日志

实现JMeter的SampleListener接口,自定义收集每个请求的测试结果,输出到控制台或自定义文件:

import org.apache.jmeter.samplers.SampleEvent;
import org.apache.jmeter.samplers.SampleListener;
import java.io.FileWriter;
import java.io.IOException;

public class CustomSampleListener implements SampleListener {
    private FileWriter writer;

    public CustomSampleListener(String logFilePath) throws IOException {
        writer = new FileWriter(logFilePath, true);
        // 写入表头
        writer.write("请求URL,响应码,响应时间(ms),响应大小(bytes)\n");
    }

    @Override
    public void sampleOccurred(SampleEvent event) {
        try {
            String url = event.getResult().getUrlAsString();
            int responseCode = event.getResult().getResponseCodeAsInt();
            long responseTime = event.getResult().getTime();
            long responseSize = event.getResult().getBytes();
            
            writer.write(String.format("%s,%d,%d,%d\n", url, responseCode, responseTime, responseSize));
            writer.flush();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void sampleStarted(SampleEvent event) {}

    @Override
    public void sampleStopped(SampleEvent event) {}

    public void close() throws IOException {
        writer.close();
    }
}

然后在测试代码中注册这个监听器:

// 创建测试树后
CustomSampleListener customListener = new CustomSampleListener("custom-test-log.csv");
testPlanTree.add(testPlanTree.getArray()[0], customListener);

// 测试结束后关闭文件流
customListener.close();

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 04:13:18