Properties, Variables & Functions
|
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.
Baseline date: 2026-10-14. This page was written against Apache JMeter 5.6.3, the latest release on that date, with Java 17 or later (21 recommended). No JMeter 6.0 release existed on that date, so any 6.0 behaviour is not described here beyond what the 5.6.3 documentation states. The load-model and plugin versions used elsewhere in this section (Plugins Manager 2.0, jmeter-maven-plugin 3.8.x, the gRPC Request plugin 2.0.x) are not needed on this page.
Almost every non-trivial test plan has values that change: the host name for each environment, the number of users, a
search term picked per iteration, a token captured from one response and sent in the next, a timestamp. JMeter gives
these values three vehicles: properties (global to the JVM), variables (local to one virtual user) and
functions (small calls such as ${__Random(1,100)} that are evaluated where they are written). This page explains
the difference between the three, how values enter a run from the command line and from files, how threads can share
data, the exact syntax and escaping rules of a function call, and a catalogue of the built-in functions grouped by
purpose. The examples use the Bookshelf scenario of this section.
Properties versus variables
| Aspect | Properties | Variables |
|---|---|---|
Scope |
Global to the JMeter JVM: all threads and all thread groups see the same value. |
Local to one thread: a thread that changes a variable changes only its own copy. |
Defined in |
|
The Test Plan or a User Defined Variables element, extractors, a CSV Data Set Config, a JSR223 element
( |
Read with |
|
|
Main use |
Configuring JMeter itself and passing run parameters (users, duration, host) into a plan. |
Per-user data: ids, tokens, search terms, extracted values. |
Case |
Case-sensitive. |
Case-sensitive. |
The user manual states the rule directly: properties are global to JMeter and are mainly used to define some of the defaults JMeter uses, while variables are local to each thread. A plan can read properties but a property cannot hold a value that is specific to one thread. The Test Plan and User Defined Variables values are available at startup, and every thread receives a copy of the initial variables when it starts. A later change, for example by a Regular Expression Extractor, applies only to the thread that made it.
Where values come from
| Source | Effect |
|---|---|
Test Plan element, User Defined Variables table |
Name and value pairs available to every thread from the start. Values may use functions and other variables. |
User Defined Variables configuration element |
Same table, as a separate element. Wherever it is placed, every User Defined Variables element is processed once at the start of the test, in tree order, not when the thread reaches its position. |
Properties |
Read with |
CSV Data Set Config, extractors, User Parameters, JSR223 elements |
Write per-thread variables during the test (covered in later pages on test data, correlation and scripting). |
Two behaviours matter when mixing them. A user-defined variable whose name equals a built-in function name overrides
that function. And an undefined variable or function reference is not an error: the text is returned unchanged and
nothing is logged, so a typo such as ${usr} appears literally in the request. Check the sampler’s request in a View
Results Tree listener during validation.
Passing values from the command line
A plan becomes reusable when its sizing is read from properties. The user manual defines the relevant options as follows.
| Option | Meaning (user manual wording) |
|---|---|
|
Defines a local JMeter property, an additional JMeter property for this JVM. |
|
Defines a JMeter property to be sent to all remote servers (used in distributed runs). |
|
Defines a Java system property value. |
|
The JMeter property file to use. |
|
Additional JMeter property file(s). |
|
Additional system property file(s). |
|
Overrides a logging level (for example |
Property loading follows a fixed order: the initial property file (jmeter.properties, or the -p file), then logging
initialisation, then user.properties, then system.properties, and finally the remaining command-line options. A
later source overrides an earlier one, so -J wins over a file. The manual recommends editing user.properties in the
bin directory, or keeping your own copy of jmeter.properties passed with -p, rather than editing the shipped
jmeter.properties in place. Property changes take effect only after JMeter restarts.
A parameterised plan
Create a Thread Group (Add → Threads (Users) → Thread Group) and, in its fields, type function calls instead of numbers. The fragment below is a Bookshelf Thread Group whose size, ramp-up and duration come from properties, with defaults suitable for a smoke run:
<ThreadGroup guiclass="ThreadGroupGui" testclass="ThreadGroup" testname="Bookshelf users" enabled="true">
<stringProp name="ThreadGroup.on_sample_error">continue</stringProp>
<elementProp name="ThreadGroup.main_controller" elementType="LoopController"
guiclass="LoopControlPanel" testclass="LoopController">
<boolProp name="LoopController.continue_forever">false</boolProp>
<intProp name="LoopController.loops">-1</intProp>
</elementProp>
<stringProp name="ThreadGroup.num_threads">${__P(threads,1)}</stringProp>
<stringProp name="ThreadGroup.ramp_time">${__P(rampup,1)}</stringProp>
<boolProp name="ThreadGroup.scheduler">true</boolProp>
<stringProp name="ThreadGroup.duration">${__P(duration,60)}</stringProp>
</ThreadGroup>
Then run it in CLI mode, overriding the defaults for the section’s load profile of 50 users, a 60 second ramp-up and a 10-minute hold (the scheduler duration includes the ramp-up, so it is 60 + 600 = 660 s):
jmeter -n -t bookshelf-load.jmx -l load.jtl -Jthreads=50 -Jrampup=60 -Jduration=660 -Jhost=localhost
With no overrides the same plan runs one user for 60 seconds. ${__P(threads)} with no default returns 1, the
function’s documented default, which makes a forgotten -J produce a smoke test instead of a failure.
A properties file avoids long command lines and can be committed per environment. Create staging.properties:
host=bookshelf.staging.example
threads=20
rampup=30
duration=300
and pass it with -q:
jmeter -n -t bookshelf-load.jmx -q staging.properties -l staging.jtl
Both are processed after user.properties and in the order they appear on the command line, so with -q
written before -J a command such as
jmeter -n -t bookshelf-load.jmx -q staging.properties -Jthreads=5 keeps the file’s other values and overrides only
threads. Remember that load is only ever aimed at localhost or systems you own; the host above is a placeholder.
The -J and -G distinction
-J defines a property in the local JVM. In a distributed run the controller does not forward it, so remote servers do
not see it. -G defines a property that is sent to all remote servers, and a -G property file is also accepted
(for example jmeter -n -t testplan.jmx -r -Gprop=val -Gglobal.properties). Use -G for anything a function on a load
generator must read, such as threads, and -J for controller-only values. The distributed testing page of this
section covers the topology.
Source: Getting Started (remote options)
Properties in 2.x/3.0 books versus 5.6
The 2.x and 3.0 era books show the same -J and __P mechanism, but older examples often read properties through
__javaScript or __BeanShell calls. Current JMeter documentation steers away from both (see the scripting group
below) and Groovy has been the default language of the JSR223 elements since 3.1. JMeter 5.5 also changed the time functions to use
DateTimeFormatter (see below).
Sharing data between threads
Variables are per thread, so a value that every thread must see is stored in a property. The function __setProperty
defines a property global to the test plan, and the manual states that such properties can be used to pass information
between threads.
<!-- In a setUp Thread Group: publish the admin token once -->
<JSR223PostProcessor guiclass="TestBeanGUI" testclass="JSR223PostProcessor" testname="Publish token">
<stringProp name="scriptLanguage">groovy</stringProp>
<stringProp name="script">props.put('adminToken', vars.get('token'))</stringProp>
</JSR223PostProcessor>
<!-- In a worker thread group: read it back as a header value -->
<stringProp name="Header.value">Bearer ${__P(adminToken)}</stringProp>
The same effect is possible without a script by calling the function in a field, for example the Value of a User
Defined Variables row: ${__setProperty(adminToken,${token})}. The function returns an empty string, or the
previous value when its third argument is true. Three rules keep the pattern safe:
-
Ordering. A property read by
__Pis read when the field is evaluated. Publish it in a setUp Thread Group, which runs before the regular thread groups, or the readers see the default. -
Race conditions. Two threads writing the same property race. Write it once and read it often.
-
Cost. Properties are one shared map, and a script that stores large objects there keeps them alive for the whole test.
Function syntax and escaping
A function call has the form ${__functionName(arg1,arg2,...)}. Functions with no arguments may omit the
parentheses, as in ${__threadNum}. The page states these rules:
| Rule | Detail |
|---|---|
Commas |
Arguments are separated by commas. A comma that belongs to an argument must be escaped with a backslash, |
Backslashes |
In a string that contains a function or variable reference, a backslash before |
Names |
Function and variable names are case-sensitive. JMeter trims spaces from variable names. |
Undefined names |
The reference is returned unchanged, with no error logged. |
Nesting |
A variable name cannot be nested directly. |
Where a function may run |
Thread-dependent functions such as |
Output variable |
Most functions take a trailing optional variable name; the result is then also stored as |
Nested references with __V, __eval and __evalVar
Three functions solve the no-nesting rule:
-
__Vevaluates a variable whose name is itself built dynamically. IfNis 3,${__V(book${N})}returns the value ofbook3. A second argument is a default. -
__evalevaluates a string, interpolating the variables and functions inside it. It is the way to expand a value that was loaded as text, for example a CSV cell that itself contains${__UUID()}. -
__evalVarevaluates the expression stored in a variable.
# book1=978-0-00-000001-0 book2=978-0-00-000002-7 N=2
${__V(book${N})} -> 978-0-00-000002-7
# template=ISBN ${book1}
${__eval(${template})} -> ISBN 978-0-00-000001-0
${__evalVar(template)} -> ISBN 978-0-00-000001-0
Escaping a script
Commas inside a __groovy call must be escaped, and the manual’s own example is
${__groovy(vars.get("myVar").substring(0\,2))}. For anything longer, store the script in a variable (a User
Defined Variables row) and reference it, which avoids the escapes. Also avoid placing variable values inside the script
text: a changing script cannot be cached, so read values through vars instead (see the scripting group below).
Source: __groovy (Functions Reference)
The Function Helper dialog
Open it from the Tools menu (Tools → Function Helper Dialog). Choose a function in the Choose a function list,
fill in the parameter table, and press Generate; the generated call, for example ${__Random(1,100,)}, can be
copied into a field. The dialog also shows the result of the last evaluation, and its parameter table lists each
argument with a short description. It does not escape values for you: a comma inside a parameter value must still be
typed as \,.
Function catalogue
Every function name below was checked against the official functions reference on 2026-10-14. In every call the variable name argument is optional unless marked required.
Random
| Function | Arguments | Notes and example |
|---|---|---|
|
Minimum (required), maximum (required), variable name. |
A random integer in the range. |
|
Length (required), characters to use, variable name. |
|
|
Format (default |
|
|
Variables separated by |
Picks one value from several variables. |
|
None. |
A pseudo-random type 4 UUID, |
Counters and thread information
| Function | Arguments | Notes and example |
|---|---|---|
|
Per-user flag TRUE or FALSE (required), reference name. |
Starts at 1 and increments by 1; the maximum is 2,147,483,647. TRUE gives each thread its own counter, FALSE a single global counter. Several calls in the same iteration do not increment it again. |
|
None. |
The current thread number, for example to build a unique user name. |
|
None. |
The name of the running thread group. |
|
First value, second value, optional further values, reference name last. |
Integer and long addition. |
Time
| Function | Arguments | Notes and example |
|---|---|---|
|
Format, variable name. |
No format returns milliseconds since the epoch. |
|
Format, date to shift (default now), duration, locale, variable name. |
ISO-style durations such as |
|
Date string (required), source format, target format (required), variable name. |
Converts a date between formats. |
The aliases can be redefined in properties, for example time.YMD=yyMMdd. Since JMeter 5.5 these functions use
DateTimeFormatter instead of SimpleDateFormat, so format letters can differ from older plans: the manual notes that
u now means year, not day-of-week number. Plans written against 2.x or 3.0 books that use SimpleDateFormat patterns
need a check.
Files
| Function | Arguments | Notes |
|---|---|---|
|
File name (required), column number (required; |
Splits lines on commas (property |
|
File name (required), variable name (default |
Each call reads the next line, and all threads share the instance. At the end of the file it wraps, unless a loop
count has been reached. Errors return |
|
File name (required), encoding (platform default), variable name. |
Reads the whole file on every call. Errors return |
|
Path (required), string (required), append (default true), encoding (default UTF-8). |
Writes a string to an absolute path. Use |
|
File, XPath expression. |
Returns the next match from an XML file on each call, wrapping at the end. |
Prefer the CSV Data Set Config for test data. File-reading functions run for every evaluation, add disk work to the
load generator and, for __FileToString, reread the entire file each time.
Scripting
| Function | Arguments | Notes |
|---|---|---|
|
Expression (required), variable name. |
Predefined variables: |
|
Expression (required), variable name. |
Commons JEXL 3, same variables as |
|
Expression, variable name. |
Commons JEXL 2, kept for older plans. |
|
Expression (required), variable name. |
Runs on Nashorn (Rhino with the property |
|
Script (required), variable name. |
Each occurrence gets its own interpreter, so variables persist across calls; the manual says |
Avoid __javaScript and __BeanShell in new plans. A function is re-evaluated on every call on every
thread, so the engine behind it sets the CPU cost per request. Groovy compiles and caches the script text, which is why
the manual says not to interpolate variable values into it; with vars.get(...) the text is constant and the compiled
script is reused.
# Avoid: the script text changes with the variable, so it cannot be cached
${__groovy("${myVar}".substring(0\,2))}
# Prefer: the text is constant
${__groovy(vars.get("myVar").substring(0\,2))}
Source: __groovy (Functions Reference)
Strings and encoding
| Function | Arguments | Notes |
|---|---|---|
|
String (required). |
application/x-www-form-urlencoded, UTF-8. Encode a search term used in a query string. |
|
String (required). |
Convert HTML entities to and from characters. |
|
String (required). |
Escapes XML 1.0 entities. |
|
String (required), mode (default |
Changes case. |
|
Algorithm (required), string (required), salt, upper-case flag (default lower case), variable name. |
MD2, MD5, SHA-1, SHA-224, SHA-256, SHA-384 and SHA-512. |
|
String to split (required), variable name (required), delimiter (default comma). |
Creates |
|
Regex (required), template (required, for example |
A reference name |
|
Numbers. |
|
|
String. |
Processes Java escapes such as |
|
String. |
Escapes ORO regular-expression meta characters. |
Information, properties and logging
| Function | Arguments | Notes |
|---|---|---|
|
Variable name. |
Local host name and IP address; useful to tag which load generator produced a sample. |
|
Variable name. |
The current sampler’s label. |
|
None. |
The test plan’s name. |
|
String (required), level (default INFO; OUT, ERR, DEBUG, INFO, WARN, ERROR), throwable text, comment. |
|
|
Property name (required), default (default |
Shorthand for a |
|
Property name (required), variable name, default. |
Returns the property, or the default; with no default and no property it returns the name. |
|
Name (required), value (required), flag to return the original value. |
Sets a global property; returns an empty string. |
|
Name (required). |
Return true or false. |
The Bookshelf plan puts several of these together. A unique reference for each loan, an ISBN picked at random from a list and an encoded search term:
POST /api/loans {"isbn":"${isbn}","ref":"loan-${__threadNum}-${__counter(TRUE,)}-${__UUID}"}
GET /api/books?query=${__urlencode(${term})}&since=${__timeShift(yyyy-MM-dd,,-P7D,,)}
Load-generator cost of functions
A function in a field is evaluated every time the field is, for every thread. A __groovy call in the Path of
an HTTP sampler runs once per request. At 500 requests per second that is 500 script evaluations per second;
Groovy’s script cache keeps each one cheap, while __BeanShell and __javaScript cost noticeably more.
The properties reference also lists function.cache.per.iteration (default false), which caches function results during
one iteration; it may give unexpected results for shared components that depend on thread variables, so leave it off
unless you have measured a need.
Source: Properties Reference
Predefined variables and properties
| Name | Meaning |
|---|---|
|
JMeter start time in milliseconds. A property, also copied to a variable of the same name. |
|
JMeter start time as |
|
JMeter start time as |
|
Test start time in milliseconds. |
|
When |
|
Reflects whether the last sample was successful; the component reference refers to it as
|
The START.* values reflect when JMeter itself started, not when the test began, and are mainly meant for file names
such as a results file per run. ${__isPropDefined(START.HMS)} returns true. Variables named in the
sample_variables property (for example SESSION_ID,REFERENCE, the value the properties reference lists and
jmeter.properties shows as a commented example) are also saved in the results file, which is how a user id
or token reference can be tied to a sample.
Pitfalls
-
A misspelt name silently stays literal. Look at the request in a listener.
-
Unescaped commas split arguments. Store long scripts and JSON bodies in a variable.
-
A trailing comma pair, as in
${__time(YMD,)}, is how an optional argument is skipped. -
__Preturns1if no default is given, which can mask a missing-Jfor a threads or loops value; always give an explicit default. -
-Jvalues do not reach remote servers; use-Gin distributed runs. -
Properties are read when evaluated, so a
__setPropertypublisher must run first. -
Thread-dependent functions evaluated at Test Plan level, or in configuration elements, return wrong values.