JMeter运行时在线程组内修改测试计划级用户定义变量方法
问题场景
当前配置结构如下:
- 测试计划层级配置用户定义变量:
fBurst=0 - Threadgroup1下挂载Once Only Controller,Controller内添加JSR223测试元件,原有代码如下:
log.info("fBurst user defined value : " + ${fBurst}) vars.put("fBurst", Integer.toString(111)) log.info("fBurst user defined value vars.put' : " + ${fBurst}) props.put("fBurst", 222) log.info("fBurst user defined value props.put' : " + ${fBurst})
相关配置截图:

执行后发现vars.put、props.put调用后,日志输出的fBurst值始终为初始值0,修改未生效。
失效根因
两个核心错误导致修改不生效:
- 占位符编译替换机制问题:JSR223脚本中直接写
${fBurst}属于JMeter的占位符语法,会在脚本第一次编译阶段就被替换为对应变量的初始值0,后续脚本运行时这几行日志代码实际执行的是log.info("xxx : 0"),无论后续怎么修改变量池的值,写死的字面量0都不会变化,本质是取值逻辑错误,不是put方法没执行成功。 - 变量作用域与优先级问题:测试计划层级的用户定义变量(UDV)会在测试计划启动初始化阶段完成加载,每个线程启动时会把UDV的初始值写入当前线程的私有变量池(vars);而props是JMeter全局属性池,
${fBurst}的取值逻辑只会查线程私有变量池和UDV初始配置,不会主动读取props中的值,所以往props里存值后直接用${fBurst}也读不到。
可行实现方案
根据使用场景选对应方案即可:
方案1:同线程内传值(绝大多数场景适用)
同线程内修改变量不需要用props,直接用vars即可,禁止在JSR223脚本中用${变量名}的形式读写变量,统一用JMeter提供的API方法取值赋值,修正后的代码:
// 读取变量初始值 log.info("fBurst初始值:{}", vars.get("fBurst")) // 修改变量值,vars只接收字符串类型入参 vars.put("fBurst", "111") // 读取修改后的值 log.info("vars修改后fBurst值:{}", vars.get("fBurst"))
代码执行后,当前线程内后续所有取样器、配置元件,无论是用${fBurst}形式引用,还是用vars.get("fBurst")读取,都能拿到更新后的111。
方案2:跨线程组传值
如果修改后的值需要给其他线程组使用,就用props存储全局属性,注意取值时必须主动从props读取,不能直接用${fBurst}:
// 存储全局属性,props支持任意数据类型,不需要转字符串 props.put("fBurst", 222) // 读取全局属性,建议设置默认值避免空指针 log.info("props修改后fBurst值:{}", props.get("fBurst"))
后续其他元件要引用这个全局值时,需要用属性函数取值,写法为${__P(fBurst,0)},括号内第二个参数为属性不存在时的默认值。
方案3:全局覆盖UDV初始值
如果需要在所有线程启动前就修改fBurst的初始值,不要把JSR223元件放在线程组下的Once Only Controller里,需要做两个调整:
- 将JSR223元件移动到测试计划根目录,放在用户定义变量配置元件的下方
- 勾选JSR223元件配置页的「在启动时执行(Execute before starting Threads)」选项
此时在JSR223里修改的值会作为UDV的初始值同步给所有后续启动的线程。
避坑提示
- 如果JSR223元件勾选了「缓存编译后的脚本(Cache compiled script if available)」,脚本内绝对不要使用
${变量名}形式的占位符,不仅会导致取值异常,还会让脚本缓存失效,大幅降低执行性能 - vars是线程私有的存储,A线程通过vars修改的值B线程无法读取,跨线程、跨线程组传值必须用props
- 不要在线程组内定义和测试计划层级UDV重名的变量,会出现优先级覆盖问题,导致值不符合预期
内容的提问来源于stack exchange,提问作者sanuboy
相关产品推荐
相关产品推荐

