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

通过Java代码运行JMeter测试生成匹配GUI的报告及空指针问题咨询

问题排查

本次出现空指针异常的核心原因如下:

  • 测试计划的HashTree结构配置错误,采样器、线程组未正确关联到测试计划,导致压测未实际执行,结果文件无有效采样数据,生成报告时读取空数据触发空指针
  • 未配置结果保存的全量必填字段,生成HTML报告需要的关键字段缺失
  • 未配置报告生成的必填参数,且未等待JMeter执行完成、所有采样结果刷入文件就启动报告生成逻辑
  • 结果文件误命名为.html后缀,实际ReportGenerator仅接受CSV/JTL格式的结果文件作为输入
解决方案

按以下步骤修正代码即可生成和JMeter GUI一致的聚合图形、统计报告:

  1. 加载JMeter配置后补充结果保存、报告生成的必填参数
  2. 修正测试计划的HashTree层级结构,保证采样器、结果收集器正常生效
  3. 等待JMeter所有压测任务执行完成、结果完全落盘后再生成报告
  4. 给HTTP采样器设置名称,保证报告中采样标签正常展示

完整可运行代码

import org.apache.commons.io.FileUtils;
import org.apache.jmeter.config.Arguments;
import org.apache.jmeter.control.LoopController;
import org.apache.jmeter.engine.StandardJMeterEngine;
import org.apache.jmeter.protocol.http.sampler.HTTPSampler;
import org.apache.jmeter.reporters.ResultCollector;
import org.apache.jmeter.reporters.Summariser;
import org.apache.jmeter.report.dashboard.ReportGenerator;
import org.apache.jmeter.testelement.TestPlan;
import org.apache.jmeter.threads.ThreadGroup;
import org.apache.jmeter.util.JMeterUtils;
import org.apache.jorphan.collections.HashTree;
import org.apache.jorphan.collections.ListedHashTree;

import java.io.File;

public class JMeterTest {
    public static void main(String[] args) throws Exception {
        StandardJMeterEngine jmeter = new StandardJMeterEngine();

        // 替换为你本地的JMeter配置路径和Home路径
        String jmeterHome = "bla/apache-jmeter-5.4.1";
        String jmeterPropPath = "bla/jmeter.properties";
        JMeterUtils.loadJMeterProperties(jmeterPropPath);
        JMeterUtils.setJMeterHome(jmeterHome);
        JMeterUtils.initLocale();

        // ========== 新增:配置结果保存必填字段 ==========
        JMeterUtils.setProperty("jmeter.save.saveservice.output_format", "csv");
        JMeterUtils.setProperty("jmeter.save.saveservice.assertion_results_failure_message", "true");
        JMeterUtils.setProperty("jmeter.save.saveservice.data_type", "true");
        JMeterUtils.setProperty("jmeter.save.saveservice.label", "true");
        JMeterUtils.setProperty("jmeter.save.saveservice.response_code", "true");
        JMeterUtils.setProperty("jmeter.save.saveservice.response_message", "true");
        JMeterUtils.setProperty("jmeter.save.saveservice.successful", "true");
        JMeterUtils.setProperty("jmeter.save.saveservice.thread_name", "true");
        JMeterUtils.setProperty("jmeter.save.saveservice.time", "true");
        JMeterUtils.setProperty("jmeter.save.saveservice.subresults", "false");
        JMeterUtils.setProperty("jmeter.save.saveservice.assertions", "true");
        JMeterUtils.setProperty("jmeter.save.saveservice.latency", "true");
        JMeterUtils.setProperty("jmeter.save.saveservice.connect_time", "true");
        JMeterUtils.setProperty("jmeter.save.saveservice.sent_bytes", "true");
        JMeterUtils.setProperty("jmeter.save.saveservice.received_bytes", "true");
        JMeterUtils.setProperty("jmeter.save.saveservice.url", "true");
        JMeterUtils.setProperty("jmeter.save.saveservice.thread_counts", "true");
        JMeterUtils.setProperty("jmeter.save.saveservice.sample_count", "true");
        JMeterUtils.setProperty("jmeter.save.saveservice.idle_time", "true");

        // ========== 新增:配置报告生成必填参数 ==========
        String reportOutputDir = "report-output/dashboard";
        JMeterUtils.setProperty("jmeter.reportgenerator.exporter.html.classname", "org.apache.jmeter.report.dashboard.HtmlTemplateExporter");
        JMeterUtils.setProperty("jmeter.reportgenerator.exporter.html.property.output_dir", reportOutputDir);
        JMeterUtils.setProperty("jmeter.reportgenerator.template_directory", jmeterHome + "/report-template");
        JMeterUtils.setProperty("jmeter.reportgenerator.overall_granularity", "1000");
        JMeterUtils.setProperty("jmeter.reportgenerator.apdex_satisfied_threshold", "500");
        JMeterUtils.setProperty("jmeter.reportgenerator.apdex_tolerated_threshold", "1500");

        // 清理历史文件
        File reportDir = new File(reportOutputDir);
        if (reportDir.exists()) {
            FileUtils.forceDelete(reportDir);
        }
        File resultFile = new File("result.csv");
        if (resultFile.exists()) {
            FileUtils.forceDelete(resultFile);
        }

        SaveService.loadProperties();

        // ========== 修正:HashTree层级结构 ==========
        HashTree testPlanTree = new ListedHashTree();
        TestPlan testPlan = new TestPlan("压测计划");
        testPlan.setUserDefinedVariables(new Arguments());
        testPlanTree.add(testPlan);

        // 构造HTTP采样器
        HTTPSampler httpSampler = new HTTPSampler();
        httpSampler.setName("库存创建接口");
        httpSampler.setDomain("host");
        httpSampler.setPort(443);
        httpSampler.setPath("/api/v1/stock-count/created");
        httpSampler.setMethod("POST");
        httpSampler.setUseKeepAlive(true);

        // 构造循环控制器
        LoopController loopController = new LoopController();
        loopController.setLoops(1);
        loopController.setFirst(true);
        loopController.initialize();

        // 构造线程组
        ThreadGroup threadGroup = new ThreadGroup();
        threadGroup.setName("压测线程组");
        threadGroup.setNumThreads(10);
        threadGroup.setRampUp(1);
        threadGroup.setSamplerController(loopController);

        // 构造结果收集器
        String summariserName = JMeterUtils.getPropDefault("summariser.name", "summary");
        Summariser summer = new Summariser(summariserName);
        ResultCollector logger = new ResultCollector(summer);
        logger.setFilename(resultFile.getAbsolutePath());

        // 按层级加入HashTree
        HashTree threadGroupTree = testPlanTree.add(testPlan, threadGroup);
        threadGroupTree.add(httpSampler, logger);

        // 执行压测
        jmeter.configure(testPlanTree);
        jmeter.run();

        // ========== 新增:等待压测完全结束、结果刷入文件 ==========
        while (jmeter.isRunning()) {
            Thread.sleep(1000);
        }
        Thread.sleep(2000);

        // 生成HTML报告
        ReportGenerator generator = new ReportGenerator(resultFile.getAbsolutePath(), null);
        generator.generate();
        System.out.println("报告生成完成,路径:" + reportOutputDir + "/index.html");
    }
}
验证

代码运行完成后,打开report-output/dashboard/index.html即可看到包含聚合统计、聚合图形、QPS曲线、响应时间分布等全套和JMeter GUI一致的可视化报告。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 14:57:04