Installation & Configuration
|
This content was generated with the assistance of AI and should be verified against the official documentation before being relied on in production. |
The reference material consulted while preparing these pages is listed in the section bibliography.
JMeter is installed by unpacking an archive: there is no installer, no service and no registry entry. That simplicity is deceptive, because almost every load-test problem that is blamed on "JMeter being slow" is really a configuration problem on the load generator: a heap that is too small, a missing driver jar, a property that was edited in the wrong file or a version that differs between machines. This page covers a clean installation and the configuration surface that matters before the first test runs.
It was written against Apache JMeter 5.6.3, the latest release at the time of writing (released 2024-01-07). The download page states that JMeter 5.6.x requires Java 8 or newer; this guide recommends Java 17 or newer and uses Java 21 in its examples. The planned JMeter 6.0 is not released: the development branch declares 6.0.0 and requires Java 17 or newer (21 recommended), so installing a current JDK now removes one upgrade step later. Where behaviour is expected to change in 6.0, the text says so. The JMeter Plugins Manager (version 2.0) is installed on the page about plugins, and the Maven plugin (jmeter-maven-plugin 3.8.x) and Docker-based runs on the page about CI/CD. The books the section draws on (JMeter Cookbook, Performance Testing with JMeter, Pro Apache JMeter) target JMeter 2.11, 2.12 and 3.0 with Java 7 or 8; their installation chapters (Cookbook appendix, PTwJ ch. 1, Pro ch. 3) are updated here to the current layout and scripts.
For what the installed pieces do once they run, see Introduction & Architecture.
Java requirements
-
Version. JMeter 5.6.3 needs Java 8 or higher; the manual advises using the latest minor version of your Java major release. Use a long-term-support JDK, 17 or 21. JMeter 6.0 (planned) requires 17 or newer, so a 17+ runtime is the safe choice for new load generators.
-
JDK versus JRE. A JDK is preferred over a JRE. The reason given in the manual is that recording HTTPS traffic needs the
keytoolutility, which ships with the JDK but not with a bare JRE. A machine that only replays tests can run on a JRE; the machine that records scripts needs a JDK. Building JMeter itself or developing plugins also needs a JDK. -
JAVA_HOME. Make sure
JAVA_HOMEpoints at the JDK or JRE you want. On Unix the launch script usesJAVA_HOMEoverJRE_HOMEwhen both are set, andJAVA_HOMEis required for thedebugargument.
Check the runtime before anything else:
java -version
echo "$JAVA_HOME"
Typical output:
openjdk version "21.0.5" 2024-10-15 LTS
OpenJDK Runtime Environment Temurin-21.0.5+11 (build 21.0.5+11-LTS)
OpenJDK 64-Bit Server VM Temurin-21.0.5+11 (build 21.0.5+11-LTS, mixed mode, sharing)
/usr/lib/jvm/temurin-21
Download and verify
The binaries are published at the official download page. For 5.6.3 the files are apache-jmeter-5.6.3.tgz and
apache-jmeter-5.6.3.zip (binaries) and apache-jmeter-5.6.3_src.tgz and apache-jmeter-5.6.3_src.zip (sources).
Every file has a matching .sha512 checksum file and a .asc PGP signature. The page insists that the integrity of
downloads must be verified with the PGP signature, and links to the Apache project’s guide on verifying releases. The
signing keys are published in the KEYS file at https://www.apache.org/dist/jmeter/KEYS.
Why it matters on a load generator: the machine will run arbitrary test plans and often sits inside a corporate or cloud network. A tampered archive is a supply-chain risk, and checking takes less than a minute.
# 1. download the archive, its checksum, its signature and the KEYS file
curl -fLO https://dlcdn.apache.org/jmeter/binaries/apache-jmeter-5.6.3.tgz
curl -fLO https://downloads.apache.org/jmeter/binaries/apache-jmeter-5.6.3.tgz.sha512
curl -fLO https://downloads.apache.org/jmeter/binaries/apache-jmeter-5.6.3.tgz.asc
curl -fLO https://downloads.apache.org/jmeter/KEYS
# 2. compare the SHA-512 digest with the published value
shasum -a 512 apache-jmeter-5.6.3.tgz
cat apache-jmeter-5.6.3.tgz.sha512
# 3. verify the PGP signature
gpg --import KEYS
gpg --verify apache-jmeter-5.6.3.tgz.asc apache-jmeter-5.6.3.tgz
The exact download mirror URLs change; take them from the download page rather than from a script written months ago.
shasum -a 512 (macOS) is sha512sum on Linux, and on Windows certutil -hashfile apache-jmeter-5.6.3.zip SHA512
gives the digest. A good signature reports Good signature from a JMeter committer; a warning that the key is not
certified means only that you have not set a trust level for it, not that the file is bad. BAD signature means do not
use the file. The checksum is fetched from the main Apache site so that it does not depend on the mirror that served
the archive.
Source: Download Apache JMeter
Then unpack it. The manual recommends avoiding spaces in the installation path, which can cause trouble, particularly in
client-server (distributed) mode, and allows renaming the top-level apache-jmeter-X.Y directory but not any of its
subdirectories.
tar -xzf apache-jmeter-5.6.3.tgz -C /opt
export JMETER_HOME=/opt/apache-jmeter-5.6.3
export PATH="$JMETER_HOME/bin:$PATH"
jmeter --version
On Windows, unzip apache-jmeter-5.6.3.zip to a path without spaces, such as C:\tools\apache-jmeter-5.6.3, and add its
bin directory to PATH.
Directory layout
The unpacked directory is called JMeter’s home. The directories below are the ones the manual describes; bin/templates
is described on the templates page.
| Directory | Contents | What you do there |
|---|---|---|
|
Launch scripts and the property files |
Edit |
|
The templates offered by File → Templates. Each template is declared in |
Add your organisation’s standard plan skeletons here so that every engineer starts from the same plan. |
|
Utility and support jars, including libraries for JDBC, JMS and other protocols. |
Drop JDBC driver jars and other plain libraries here. JMeter does not bundle JDBC drivers or JMS client jars. |
|
JMeter components and plugins (the jar of the Plugins Manager goes here). |
Put plugin jars only; do not put utility or dependency jars here. |
|
Jars for the JUnit Request sampler. |
Place your compiled JUnit test jars here when you use that sampler. |
|
The HTML documentation and the Javadoc. |
Read offline. |
|
Printable form of the user manual. |
Read or print offline. |
|
Additional files such as example build files, sample plans and helper resources. |
Look here for extras that are not part of the core runtime. |
|
Licence files for JMeter and its third-party libraries. |
Compliance only. |
The manual’s table lists bin, docs, extras, lib, lib/ext, lib/junit, licenses and printable_docs; the
description of what extras contains is deliberately general because the manual gives only "additional files".
jmeter.log is created in the directory the script was launched from, not in bin, unless the log file is redirected
(see Logging below). Always start scripts from a working directory you control, such as the project’s test directory, so
that the log and any relative paths (CSV files, result files) resolve there.
Launch scripts
| Script | Purpose |
|---|---|
|
Start JMeter, in GUI mode by default. |
|
Starts JMeter without a Windows console window. |
|
Windows drag and drop: run a dropped |
|
Start JMeter in server mode, waiting for a controller; used in distributed tests. |
|
Start the JMeter Mirror Server in CLI mode, a simple server that echoes requests, useful for tests. |
|
Gracefully stop a running CLI-mode instance (waits for current samples). |
|
Abruptly stop a running CLI-mode instance. |
Two rules shape everything that follows. First, the GUI is for creating, debugging and checking scripts; load must be
generated in CLI mode (-n), which is covered in the page on running tests in CLI mode. Second, anything that
behaves differently when started from a launcher script and when started with java -jar ApacheJMeter.jar (JVM
options, language, GC) comes from the script, so always use the script.
jmeter # GUI
jmeter -n -t bookshelf-load.jmx -l results.jtl # CLI mode
./shutdown.sh # from another terminal: graceful stop of a CLI run
JVM options and the heap
The scripts read environment variables, so no script has to be edited. The ones the manual documents:
| Variable | Meaning | Default (documented) |
|---|---|---|
|
Heap and metaspace sizing. |
|
|
Garbage collector choice and tuning. |
|
|
Extra JVM arguments. On Windows it is added last to the Java command; on Unix it is added before |
empty |
|
Java runtime options used at startup (Unix). |
empty |
|
When set, only |
unset |
|
The language and region of the JVM. |
|
|
Installation locations; guessed from the script location when unset. |
derived |
|
Which Java to run (Unix). |
from the environment |
On Windows the scripts additionally use DDRAW (direct-draw options, empty by default) and JM_LAUNCH (the Java
executable, java.exe by default or javaw.exe).
Settings you want on every run go in a file that the script sources: bin/setenv.sh on Unix (the jmeter script
sources it) or bin\setenv.bat on Windows. Settings for one run go on the command line.
# bin/setenv.sh
export HEAP="-Xms2g -Xmx2g -XX:MaxMetaspaceSize=256m"
export JVM_ARGS="-Dfile.encoding=UTF-8"
# one run only
JVM_ARGS="-Xms1024m -Xmx1024m" jmeter -n -t bookshelf-load.jmx -l results.jtl
For Windows the manual’s example for bin\setenv.bat is set JVM_ARGS=-Xms1024m -Xmx1024m -Dpropname=value.
Sizing the heap: worked reasoning. The manual does not give a threads-per-gigabyte figure, and any such number
depends on the plan, so measure. A method that works: run the real plan at the planned thread count with the default
1 GiB heap and watch garbage-collection behaviour (enable -Xlog:gc* through JVM_ARGS on Java 9+). If a full-heap
collection occurs often or an OutOfMemoryError appears in jmeter.log, double HEAP and repeat. Keep -Xms equal to
-Xmx so the heap does not resize during the test, and keep the heap below the machine’s free RAM minus the operating
system and any co-located tools, otherwise the load generator swaps and the test measures the generator rather than the
system under test. Heap, listeners, assertions and response-body retention are what drive memory; the page on best
practices and load-generator tuning goes into these.
GUI mode costs far more than CLI mode because every sampler result can be kept by a listener in memory. Never run a load test from the GUI, and do not size the heap from a GUI trial.
Properties files and their load order
JMeter reads three property files from bin:
| File | Role |
|---|---|
|
The default JMeter properties, many commented. It is replaced on every upgrade, so editing it makes upgrades painful.
The |
|
Your overrides. The properties reference says changes here take effect only after JMeter is restarted. This is where site-specific settings belong, because it survives copying and is easy to diff. |
|
Java system properties (for example SSL settings) that JMeter sets at startup. The same properties can be given with
|
The manual gives the load order: the -p option is read first, then jmeter.properties (or the file given with -p)
is loaded; then the -j log file is set; logging is initialised; then user.properties is loaded; then
system.properties; and finally all other command-line options are processed. -q additional property files and -J
properties are handled after user.properties, and -S and -D after system.properties. The practical consequence
is that a later source wins: -Jthreads=20 on the command line overrides threads=10 in user.properties, which in
turn overrides the default in jmeter.properties.
| Option | Effect |
|---|---|
|
Use this property file instead of |
|
Additional property file(s) loaded after |
|
Define a local JMeter property, |
|
Define a property that is sent to all remote servers, or a property file (distributed tests). |
|
Define a Java system property, |
|
Additional system property file(s). |
|
The JMeter home directory. |
A parameterised run, with the property read inside the plan by the ${__P(threads,10)} function (properties and
functions are covered on the page about properties, variables and functions):
# bin/user.properties
threads=10
rampup=60
jmeter -n -t bookshelf-load.jmx -l results.jtl -Jthreads=50 -Jrampup=120 -Jjmeter.save.saveservice.output_format=csv
With those arguments threads is 50 and rampup 120, while anything else comes from user.properties. Passing a
property on the command line is visible to other users who can list processes, a warning the manual makes; do not
pass secrets that way.
Classpath
JMeter is started with java -jar, so the CLASSPATH environment variable has no effect. The ways to add code are:
| Location | Use |
|---|---|
|
Utility jars, plus JDBC drivers, JMS clients and other support libraries. Only |
|
JMeter components and plugins only. Do not put utility or dependency jars here. |
|
Extra locations searched for plugin classes (GUI elements, samplers), in addition to |
|
Utility and plugin-dependency locations, added to the system and JMeter class loaders. Separated by the platform path separator. Empty by default; paths with spaces can cause problems with the JVM. |
|
Locations of classes that plugins depend on, added to JMeter’s internal loader only. The manual prefers it for
plugin dependencies. Separated by |
JDBC and JMS jars are not bundled. The JDBC Connection Configuration element fails with a class-not-found error
until the driver jar for your database is in lib (or on one of the paths above). The same is true for JMS provider
client libraries. Get the jars from the vendor.
# user.properties
user.classpath=/opt/jmeter-extra/drivers
plugin_dependency_paths=/opt/jmeter-extra/plugin-deps
search_paths=/opt/jmeter-extra/plugins
Restart JMeter after changing any of these. A frequent mistake is dropping a library into lib/ext, where JMeter scans
it for components, wasting startup time and sometimes loading it in the wrong class loader. Planned JMeter 6.0 changes
in the way plugins are loaded are not detailed in the official documentation; in 5.6 plugins can also be found through
Java’s ServiceLoader mechanism.
Logging
Since JMeter 3.2, logging uses Apache Log4j 2 and is configured by log4j2.xml, looked for by default in the directory
JMeter is launched from. Code, including plugins, must log through SLF4J. The default root level is info and the
default log file is jmeter.log.
<Configuration status="WARN" packages="org.apache.jmeter.gui.logging">
<Appenders>
<File name="jmeter-log" fileName="${sys:jmeter.logfile:-jmeter.log}" append="false">
<PatternLayout>
<pattern>%d %p %c{1.}: %m%n</pattern>
</PatternLayout>
</File>
</Appenders>
<Loggers>
<Logger name="org.apache.http" level="debug" />
<Root level="info">
<AppenderRef ref="jmeter-log" />
</Root>
</Loggers>
</Configuration>
The XML above is a minimal illustration. The manual shows enabling HTTP client diagnostics by adding the
<Logger name="org.apache.http" level="debug" /> line. For a one-off run, avoid editing the file and use the
command line:
jmeter -n -t bookshelf-load.jmx -l results.jtl -j bookshelf-run.log # change the run log file
jmeter -Ljmeter.engine=DEBUG # one category
jmeter -LDEBUG # root level
jmeter -i my-log4j2.xml -n -t bookshelf-load.jmx # alternative logging configuration
In the GUI, Options → Log Viewer shows the log, and an error counter at the top right turns up when something has been logged at error level. Heavy DEBUG logging is itself load on the generator (disk I/O and CPU), so do not leave it on for a measured run.
Outbound proxy
If the load generator reaches the system under test through a corporate proxy, tell JMeter on the command line. These options apply to the whole JMeter process:
| Option | Meaning |
|---|---|
|
Proxy host name or address. |
|
Proxy port. |
|
Hosts that bypass the proxy, for example |
|
Proxy user name. |
|
Proxy password. |
|
Proxy scheme (shown in the manual’s proxy section). |
jmeter -E https -H my.proxy.server -P 8000 -u USER -a PASSWORD -N localhost
jmeter -n -t bookshelf-load.jmx -l results.jtl -H my.proxy.server -P 8000
Use placeholders as above; a real password on the command line is visible to other users of the machine. The
properties reference lists http.proxyUser, http.proxyPass and http.proxyDomain (for NTLM) for the HTTP sampler’s
proxy authentication. Per-request proxy settings can also be set on each HTTP Request sampler, and then override
these global ones. The proxy used by the recorder is a different thing and is covered on the recording page.
Aim the Bookshelf API at localhost, which needs no proxy and is excluded with -N localhost.
Running JMeter in Docker
The Apache JMeter project publishes no official Docker image and the official documentation describes only CLI mode
for automation. Community images exist, for example justb4/jmeter and alpine/jmeter; they are third-party, and
their JMeter and Java versions should be checked before use. The alternative is a small Dockerfile of your own that
unpacks the official binary, which makes the version explicit and lets you add the JDBC drivers and plugins your plans
need.
FROM eclipse-temurin:21-jre
ARG JMETER_VERSION=5.6.3
ENV JMETER_HOME=/opt/apache-jmeter-${JMETER_VERSION}
ENV PATH=${JMETER_HOME}/bin:${PATH}
RUN apt-get update \
&& apt-get install -y --no-install-recommends curl \
&& rm -rf /var/lib/apt/lists/* \
&& curl -fL -o /tmp/jmeter.tgz https://archive.apache.org/dist/jmeter/binaries/apache-jmeter-${JMETER_VERSION}.tgz \
&& curl -fL -o /tmp/jmeter.tgz.sha512 https://archive.apache.org/dist/jmeter/binaries/apache-jmeter-${JMETER_VERSION}.tgz.sha512 \
&& echo "$(cut -d' ' -f1 /tmp/jmeter.tgz.sha512) /tmp/jmeter.tgz" | sha512sum -c - \
&& tar -xzf /tmp/jmeter.tgz -C /opt \
&& rm /tmp/jmeter.tgz /tmp/jmeter.tgz.sha512
# JDBC drivers and other plain libraries go in lib, plugin jars in lib/ext
COPY drivers/*.jar ${JMETER_HOME}/lib/
WORKDIR /test
ENTRYPOINT ["jmeter"]
docker build -t bookshelf-jmeter:5.6.3 .
docker run --rm -v "$PWD":/test bookshelf-jmeter:5.6.3 \
-n -t bookshelf-load.jmx -l results.jtl -e -o report
The Dockerfile is an illustration rather than an official artefact: it takes the checksum from the same archive host
(a weaker check than the PGP verification described above, which you can add), and the base image and archive URL should be
confirmed against the download page. Pass -Jname=value arguments to the container the same way as to the local script, and
set JVM_ARGS with -e to adjust the heap. Mount the test directory so that the log, the results and the CSV data live
outside the container. Containers started on a Linux host with --network host or on the Compose network can reach the
Bookshelf API; from inside a container localhost is the container itself, not the host. Distributed runs in
containers and CI are covered in the later pages on distributed testing and CI/CD.
Keeping versions aligned across machines
In distributed testing the controller and every server run the whole plan, so they must run the same JMeter version and the same Java version; data files such as CSV inputs are not sent and must exist on each node. The same discipline applies to your own workstation, the CI agent and the load generators:
-
Pin one JMeter version in a file in the test repository (or a Dockerfile argument as above) and upgrade all machines together.
-
Pin the Java major version and the plugin versions installed with the Plugins Manager; a
.jmxsaved by a newer version may reference elements an older one does not have. -
Keep configuration in
user.properties,setenv.shand-Jarguments under version control, rather than editingjmeter.propertiesper machine. -
Treat drivers and plugins as part of the version. The same jars must be present on every node.
-
Record the version with each result: the first lines of
jmeter.logand the run output state the JMeter and Java versions. -
Plan for 6.0. Planned 6.0 changes include Java 17 as a minimum, the removal of MongoDB elements and a different MySQL driver class name; test plans that use them need review before moving the whole fleet.
Check what a machine has:
jmeter --version
java -version
ls "$JMETER_HOME/lib/ext" "$JMETER_HOME/lib" | head
Changes since the books
| Topic | Books (JMeter 2.x / 3.0, Java 7 or 8) | JMeter 5.6.3 |
|---|---|---|
Java |
Java 7 or 8 (Cookbook, PTwJ, Pro). |
Java 8 or newer; 17 or newer recommended; 6.0 (planned) requires 17+. |
Logging |
Logging set up the older way (the books predate the move to Log4j 2). |
Log4j 2 with |
Plugin installation |
Unzip plugin sets into |
The Plugins Manager (separate page); |
Mode names |
"Non-GUI mode". |
CLI mode. |
Distributed security |
Plain RMI between master and slaves. |
RMI over SSL by default since 4.0 (covered under distributed testing). |
Memory settings |
Edit |
Set |