In Apache JMeter's bin/jmeter launcher, which environment variable sets the JVM heap, and what is its default?
answer
- A launcher variable, not a property
- Read before the JVM even starts
- Initial and maximum ship equal
- bin/setenv.sh is the sanctioned place
basics
~10 sHEAP. Apache JMeter's bin/jmeter launcher defaults it to -Xms1g -Xmx1g -XX:MaxMetaspaceSize=256m, so an injector starts with a fixed one-gigabyte heap unless HEAP is exported first, normally from bin/setenv.sh.
solid answer
~40 s`HEAP` is the environment variable Apache JMeter 6.0.0's `bin/jmeter` script reads to build the memory part of the injector's `java` command line. The script applies it as a shell default, `: "${HEAP:="-Xms1g -Xmx1g -XX:MaxMetaspaceSize=256m"}"`, so an already-exported value wins and an unset one falls back to a fixed 1 GB heap plus a 256 MB metaspace cap. It is not a JMeter property — no entry in `jmeter.properties` can change it, because the heap is fixed before the JVM starts. Because `bin/jmeter` sources `bin/setenv.sh` (a file you create; Apache does not ship it) before computing that default, exporting `HEAP` there is the supported way to raise an injector past the shipped gigabyte, and it survives an upgrade because the launcher itself is untouched.
code
bash · 6 lines# bin/setenv.sh - you create this file; Apache does not ship it.
# bin/jmeter sources it before it computes any default.
export HEAP="-Xms4g -Xmx4g -XX:MaxMetaspaceSize=256m"
# One-off equivalent, scoped to a single run:
# HEAP="-Xms4g -Xmx4g -XX:MaxMetaspaceSize=256m" jmeter -n -t plan.jmx -l results.jtlgo deeper
Recall the name and the number: the variable is HEAP and the shipped default is a fixed one-gigabyte heap. Knowing that a stock JMeter starts at 1 GB is the point of the question.
Explain the mechanics: bin/jmeter sources bin/setenv.sh first, then applies HEAP as a shell default, then expands it into the java command line. Name the metaspace flag that rides along in the same string.
Show that you verify rather than assume. Point at the Max memory line jmeter.log records at startup, and know that jmeter-server inherits the same default so a fleet needs the setting everywhere.
Own the policy: one documented HEAP per machine class in setenv.sh, no edits to the shipped launcher, and a rule that says the number is a machine decision rather than something each run improvises.
## The variable, not a property Apache JMeter 6.0.0 sizes the injector JVM from a shell environment variable named `HEAP`, read by `bin/jmeter` on Un*x and by `bin/jmeter.bat` on Windows. It is **not** a JMeter property: nothing you put in `bin/jmeter.properties`, `bin/user.properties` or `bin/system.properties` can change the heap, because the heap has to be fixed on the `java` command line before the JVM that would read those files exists at all. `bin/jmeter` assigns it with a shell default: ```sh : "${HEAP:="-Xms1g -Xmx1g -XX:MaxMetaspaceSize=256m"}" ``` The `:=` form keeps an already-set, non-empty `HEAP` and falls back to the shipped string otherwise. `HEAP` is then expanded into the `ARGS` list the script hands to `java`. ## What the shipped default contains - `-Xms1g` — the initial heap. - `-Xmx1g` — the maximum heap; initial and maximum ship **equal**. - `-XX:MaxMetaspaceSize=256m` — a metaspace cap, which is a separate region from the heap and is *not* raised when you raise `-Xmx`. That gigabyte is a JMeter 4.0 change; older releases shipped `-Xms512m -Xmx512m`. The Getting Started manual's own load-run checklist lists "Increase the Java Heap size" as a step, noting the default "might not be enough for your test". Two neighbouring assignments in the same script matter as soon as you raise it: - `GC_ALGO` defaults to `-XX:+UseG1GC -XX:MaxGCPauseMillis=100 -XX:G1ReservePercent=20`. (The user manual's variable table still prints `250` for the pause target; the shipped scripts say `100`, and the scripts are what runs.) - `DUMP` is set unconditionally to `-XX:+HeapDumpOnOutOfMemoryError`, with the comment "Always dump on OOM (does not cost anything unless triggered)". No `-XX:HeapDumpPath` is set anywhere in the distribution. ## Where to set it 1. **`bin/setenv.sh`** (`setenv.bat` on Windows). Apache does not ship this file — you create it. `bin/jmeter` sources it near the top, long before the `HEAP` default is computed, so an `export HEAP=...` there wins. This is the documented route, and because the launcher itself is never edited, a JMeter upgrade cannot silently discard it. 2. **An exported variable for a single run**, e.g. `HEAP="-Xms4g -Xmx4g -XX:MaxMetaspaceSize=256m" jmeter -n -t plan.jmx -l results.jtl`. Same effect, scoped to that invocation. 3. **`JVM_ARGS`**, which the launcher appends *after* `ARGS`, so a `-Xmx` there overrides the one `HEAP` already placed on the line instead of replacing the whole string. Editing `bin/jmeter` in place is the fourth option and the one the script's own header warns against: "Do not set the variables in this script. Instead put them into a script `setenv.sh` in `JMETER_HOME/bin` to keep your customizations separate." ## Confirming the value took effect `org.apache.jmeter.JMeter` logs a startup block at INFO into `jmeter.log` that includes `java.version=`, `java.vm.name=` and a `Max memory =` line carrying `Runtime.getRuntime().maxMemory()` **in bytes**. An injector you believe you raised to four gigabytes should show roughly `4294967296` there; a value near a gigabyte means your `HEAP` never reached the launcher. ## The launcher variables side by side | Variable | Shipped default | How it reaches `java` | |---|---|---| | `HEAP` | `-Xms1g -Xmx1g -XX:MaxMetaspaceSize=256m` | inside `ARGS` | | `GC_ALGO` | `-XX:+UseG1GC -XX:MaxGCPauseMillis=100 -XX:G1ReservePercent=20` | inside `ARGS` | | `VERBOSE_GC` | unset; two commented-out candidates | inside `ARGS` | | `JVM_ARGS` | empty | appended after `ARGS` | | `JMETER_COMPLETE_ARGS` | empty | when set, `ARGS` is emptied | ## One launcher, several entry points `bin/jmeter-server` is a thin wrapper that calls `bin/jmeter`, so a remote engine inherits the same one-gigabyte default as a local run. `bin/jmeter.sh` does the opposite: it sets `JMETER_COMPLETE_ARGS=true`, which makes `bin/jmeter` skip `HEAP` altogether. What in a plan consumes that heap, and what evidence shows the heap was the constraint, are separate subjects — this one ends at the launcher's command line.
- Where would you confirm that the heap you set actually reached the JVM?In `jmeter.log`. `org.apache.jmeter.JMeter` logs a startup block at INFO with `java.version=`, `java.vm.name=` and `Max memory =`, the last carrying `Runtime.getRuntime().maxMemory()` in bytes. A four-gigabyte injector reports roughly 4294967296; a number near a gigabyte means the launcher used its own default.
- Does raising -Xmx also raise the metaspace cap the default sets?No. `-XX:MaxMetaspaceSize=256m` is a separate flag inside the same `HEAP` string and covers a different region. If you override `HEAP` you replace the whole string, so carry the metaspace flag over deliberately; if you patch only `-Xmx` through `JVM_ARGS`, the shipped 256 MB cap stays exactly as it was.
- Does a remote engine started with bin/jmeter-server get a different default?No. `bin/jmeter-server` is a thin wrapper whose last line calls `bin/jmeter` with `-s` and a server port, so it inherits the same `HEAP` default and the same `bin/setenv.sh`. Raising the heap on a generator fleet therefore means setting `HEAP` on each machine, not only on the machine you launch from.
saying these in an interview costs you the question
- Says the heap is configured in jmeter.properties
- Edits bin/jmeter directly instead of creating bin/setenv.sh
- Thinks -Xmx1g is a per-thread allowance
- Claims JMeter ships with no heap limit at all
- Confuses HEAP with the plan's own memory use