Which objects does JMeter bind for a script named by the jsr223.init.file property?
answer
- No context object is involved at all
- Count the bindings on one hand
- Anything context-shaped is missing
- Only the JVM-wide store is writable there
basics
~20 sOnly three: log, props and OUT. JMeter builds that script's bindings by hand in its own startup path and never touches a JMeterContext, so there is no vars, ctx, prev, sampler, Label, FileName, Parameters or args at all.
solid answer
~30 s`jsr223.init.file` points at a script JMeter evaluates once during startup. `JMeter.java` creates the bindings by hand for it and puts exactly three things in: `log` (a logger named `jsr223.init.file`), `props` (the JVM-wide `java.util.Properties`) and `OUT` (`System.out`). The comment block in `bin/jmeter.properties` documents the same three. Everything a JSR223 *element* gets — `vars`, `ctx`, `prev`, `sampler`, `Label`, `FileName`, `Parameters`, `args` — is missing, because the element bindings are read out of a `JMeterContext` and this code never touches one. The engine is chosen from the file's extension and falls back to Groovy when the extension is blank or no engine matches.
go deeper
Recall that a startup script is configured by a property rather than added to the plan, and that it cannot touch variables at all - only log, props and OUT are there.
Explain why the binding set shrinks to log, props and OUT: an element reads its bindings from a JMeterContext and its own fields, while JMeter builds these three by hand and touches neither.
Use it to prime an injector, but know that in a non-GUI run JMeter calls it after submitting the test, and that a read failure is only logged - so never let the first sampler depend on it.
Decide whether injectors are allowed a startup hook at all: it is machine-local configuration that no plan file records, so it can make one generator behave unlike the rest of the fleet.
`jsr223.init.file` is a JMeter property, not an element. Setting it makes JMeter evaluate one script during startup, and the binding set it receives is deliberately much smaller than the one a JSR223 element gets. ## The three bindings `JMeter.java` builds them explicitly: - `log` — an SLF4J `Logger` named `jsr223.init.file`, so a `<Logger name="jsr223.init.file" .../>` entry in `bin/log4j2.xml` controls exactly this script's output - `props` — the same JVM-wide `java.util.Properties` instance that `JMeterUtils.getJMeterProperties()` returns, and that a JSR223 element's `props` binding points at - `OUT` — `System.out` The commented block in `bin/jmeter.properties` above the key lists the same three. ## Why the rest is absent A JSR223 element's bindings are read out of `JMeterContextService.getContext()` and off the element itself. `runInitScripts` does neither — it calls `engine.createBindings()` and puts three entries in by hand: | Missing binding | Where an element would have got it | |---|---| | `vars` | a thread's `JMeterVariables`, via the context | | `ctx` | `JMeterContextService.getContext()` | | `prev`, `sampler` | the context's previous result and current sampler | | `Label`, `FileName`, `Parameters`, `args` | the test element's own fields | That leaves `props` as the only writable channel out of the script — which is the point. An init script's real job is to set properties, register something on the classpath, or prime a static cache, so that plans can read the values through `${__P(...)}` or a script's `props` binding once the run begins. ## When exactly it runs `runInitScripts()` is called from `startOptionalServers()`, and JMeter calls that in three places: after registering the RMI server for `-s`, after launching the GUI, and — in non-GUI mode — **after** `startNonGui(...)`. That last one matters. `StandardJMeterEngine.runTest()` submits the run to an executor and returns immediately, so in a `-n` run the init script and the plan's first threads can be starting at the same time. Do not write a plan whose first sampler depends on a property the init script sets; seed that property with `-J`, a `-q` file or `user.properties` instead, and keep the init script for work whose effect is only needed later. ## How the engine is chosen JMeter takes the file's extension and asks the `ScriptEngineManager` for an engine by that extension. If the extension is blank it uses `Groovy`; if no engine matches, it logs a warning listing the engines and their extensions and falls back to `Groovy` by name. If the file does not exist or is not readable, JMeter logs an error naming the property and carries on — the run is not stopped. ## Practical notes 1. Set it like any other property, in `bin/user.properties`, in a file passed with `-q`, or with `-J` on the command line — no element and no plan edit is involved. 2. It runs once per JVM. A `jmeter-server` process reaches `startOptionalServers()` too, so in a distributed run every engine JVM runs its own copy; nothing is shipped from the controller. 3. Errors are logged, not fatal, so a broken init script produces a run that looks normal but is missing whatever the script was meant to set. Log a confirmation line and assert on the property early in the plan if the run depends on it. 4. Do not confuse it with the BeanShell startup hooks (`beanshell.init.file` and the per-element `.bshrc` init properties), which belong to a different scripting family.
- What happens in JMeter when the file named by jsr223.init.file cannot be read?JMeter logs an error naming the file and the property and continues starting up. The run proceeds without whatever the script was meant to set, so a plan depending on it should confirm the value early rather than assume it.
saying these in an interview costs you the question
- Expects vars to be available in a startup script
- Thinks the init file is a test element in the plan
- Assumes a missing init file aborts JMeter startup
- Trusts the init script to finish before the first sampler
- Confuses it with the BeanShell init file property