skip to content

In Apache JMeter's bin/jmeter launcher, which environment variable sets the JVM heap, and what is its default?

level: juniorimportance: must knowfreq 68%

answer

  1. A launcher variable, not a property
  2. Read before the JVM even starts
  3. Initial and maximum ship equal
  4. bin/setenv.sh is the sanctioned place

basics

~10 s

HEAP. 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
bash
# 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.jtl

go deeper

for a junior

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.

for a middle

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.

for a senior

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.

for a principal

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