skip to content

In JMeter, how do the search_paths, user.classpath and plugin_dependency_paths properties differ?

level: middleimportance: should knowfreq 41%

answer

  1. Three properties, all shipped commented out
  2. One extends plugins, two extend dependencies
  3. Only one of the three is scanned, not just loaded
  4. The separator is not the same throughout

basics

~10 s

search_paths adds directories JMeter scans for plugin components, alongside lib/ext. user.classpath and plugin_dependency_paths add directories of dependency jars alongside lib; user.classpath also joins the system classpath, plugin_dependency_paths reaches JMeter's own loader only.

solid answer

~60 s

All three live in `bin/jmeter.properties`, all three are shipped commented out, and all three name **path items**: each entry is either a directory, whose `.jar` files are then added automatically, or a single `.jar` file added on its own. What none of them do is recurse - jars in sub-directories are ignored. `search_paths` extends the component search path: its directories are searched for plugin classes *in addition to* `lib/ext`. `user.classpath` and `plugin_dependency_paths` both extend the dependency path *in addition to* `lib`. The difference between those two is reach: entries from `search_paths` and `user.classpath` are added to JMeter's loader **and** appended to the `java.class.path` system property, while `plugin_dependency_paths` entries reach JMeter's internal loader only - which is why the properties file tells you to prefer `plugin_dependency_paths` for plugin dependencies. Scanning is decided separately and by neither flag: JMeter's class finder walks exactly `JMeterUtils.getSearchPaths()`, which is `lib/ext` followed by the `search_paths` entries and nothing else, so a `user.classpath` directory is loadable but is never scanned for components. Separators differ too: `search_paths` and `plugin_dependency_paths` split on `;`, `user.classpath` on the platform path separator.

go deeper

for a junior

Know that these three properties exist so plugin and dependency jars can live outside the JMeter installation, and that each entry is a path item - a directory whose jars are picked up automatically, or a single jar file.

for a middle

Explain the split: search_paths extends the plugin search path beside lib/ext, while user.classpath and plugin_dependency_paths extend the dependency path beside lib.

for a senior

Demonstrate reading the startup log to tell 'Adding to classpath and loader' from 'Adding to loader', and diagnosing a silently skipped path from a separator or typo.

for a principal

Decide whether injectors get a fixed installation with vendored jars or a properties-driven layout per project, and who owns the resulting startup cost and reproducibility.

In Apache JMeter 6.0.0 the shipped directories `lib` and `lib/ext` cover the ordinary case, but plenty of teams cannot write into the JMeter installation at all - it is baked into a container image, owned by another team, or shared between projects that need different plugin sets. Three properties in `bin/jmeter.properties` exist for that, and they are not interchangeable. ## What each one is for - **`search_paths`** - "List of directories to search for additional JMeter plugin classes, for example new GUI elements and samplers." Its value is *in addition to* any jars found in `lib/ext`. The properties file adds a warning: do not use this for utility or plugin dependency jars. - **`user.classpath`** - directories JMeter searches for utility and plugin dependency classes, *in addition to* any jars found in `lib`. All entries are added to the class path of the system class loader **and** to the path of JMeter's internal loader. - **`plugin_dependency_paths`** - the same purpose as `user.classpath`, but all entries are added to the path of the JMeter internal loader **only**. The file states outright that for plugin dependencies this property should be used instead of `user.classpath`. ## The mechanism behind the difference JMeter calls a small helper once per property at startup. Two of them take a flag meaning "also put this on the system classpath": 1. `search_paths` is processed with that flag **on**. 2. `user.classpath` is processed with that flag **on**. 3. `plugin_dependency_paths` is processed with that flag **off**. When the flag is on, the entry itself, plus each `.jar` inside it when it is a directory, is added to JMeter's dynamic loader *and* appended to the `java.class.path` system property; when it is off, only the loader is touched. What the flag does **not** decide is scanning. `ClassFinder` never reads `java.class.path` - it walks exactly the array it is handed, and for JMeter components that array is `JMeterUtils.getSearchPaths()`: `JMETER_HOME/lib/ext` followed by the `search_paths` entries. So `search_paths` is scanned because `getSearchPaths()` names it, while `user.classpath`, flag on though it is, is loaded but never scanned - `NewDriver`'s own "ClassFinder needs this" comment beside the append is a leftover from a much older release, so do not take it at face value. All the flag still buys is a place on the classpath *string* for the handful of things that inspect it, which is narrow; a dependency jar needs neither that nor the scan, which is exactly why the properties file steers plugin dependencies to `plugin_dependency_paths`. | Property | Adds to | Scanned for components | Separator | In addition to | |---|---|---|---|---| | `search_paths` | loader + system classpath | yes | `;` | `lib/ext` | | `user.classpath` | loader + system classpath | no | platform path separator | `lib` | | `plugin_dependency_paths` | JMeter loader only | no | `;` | `lib` | ## Details that decide whether it works - **A directory or a single jar.** The manual says of all three that "a path item can either be a jar file or a directory". Name a directory and any `.jar` directly inside it is included automatically; name one jar file and just that jar is added. Either way there is no recursion - jars in sub-directories are ignored, exactly as for `lib` and `lib/ext`. - **Unreadable entries are warnings, not errors.** A path that is neither readable nor a directory is logged as a warning and skipped, so a typo produces a plugin that is simply absent rather than a failed startup. Check the log for the `search_paths=` / `user.classpath=` line JMeter prints back, and for `Adding to classpath and loader:` versus `Adding to loader:`. - **The separator really is `;` for two of them.** `search_paths` and `plugin_dependency_paths` are split on a literal semicolon on every platform, while `user.classpath` is split on the platform path separator - a colon on Linux and macOS. Writing a colon-separated `search_paths` on Linux yields one long nonsense path. - **Spaces in paths may cause problems for the JVM**, which the properties file warns about directly. - **They are all unset by default.** Every one of the three is commented out in the shipped `bin/jmeter.properties`, so nothing changes until you set it, typically in `user.properties` rather than by editing the shipped file. ## Choosing between them Use `search_paths` when the plugin JARs themselves live outside the installation - a per-project directory of vendored plugins, for instance. Use `plugin_dependency_paths` for the libraries those plugins need, so JMeter can load them without putting them on the system class loader as well. Reach for `user.classpath` only when something genuinely needs the jars on the system class loader as well, which is the narrower case; the JUnit Request sampler's class chooser, for example, reads `user.classpath` explicitly when it looks for test classes. Whatever you choose, set it in `user.properties` or pass it with a property flag rather than editing the shipped `jmeter.properties`, so the next JMeter upgrade does not quietly discard it.

  • Why does the properties file tell you to prefer plugin_dependency_paths over user.classpath for plugin dependencies?
    Because `user.classpath` entries are also pushed onto the system class path, while `plugin_dependency_paths` entries reach JMeter's internal loader alone. A plugin's dependency only has to resolve inside JMeter, so the narrower loader gives identical class resolution without widening what the rest of the JVM can see - which is exactly the reason `bin/jmeter.properties` says to use `plugin_dependency_paths` instead of `user.classpath` for plugin dependencies. Note that neither property is scanned for JMeter components: the class finder walks `lib/ext` plus `search_paths` only.
  • Where should you set these properties so a JMeter upgrade does not lose them?
    In `bin/user.properties`, which JMeter loads after `jmeter.properties`, or on the command line. Editing the shipped `jmeter.properties` works but the file is replaced by the next installation, so any local edits have to be re-applied by hand.
  • A search_paths value written with colons on Linux finds nothing. Why?
    `search_paths` is split on a literal semicolon on every platform, not on the platform path separator, so a colon-separated value is read as a single path name that does not exist. JMeter logs it as unreadable and moves on. Only `user.classpath` uses the platform path separator.

Think of a workshop. The tool rack by the door is walked past and inventoried every morning, so anything on it gets noticed; the parts bins at the back are only opened when a job asks for a part. search_paths adds another rack to the morning walk; user.classpath and plugin_dependency_paths add parts bins, the first of them shared with the rest of the workshop.

saying these in an interview costs you the question

  • Treats the three properties as interchangeable aliases
  • Thinks the entries are read per test run rather than once at startup
  • Assumes every entry is scanned for JMeter components
  • Uses the platform path separator for search_paths everywhere
  • Expects jars in sub-directories of an entry to be picked up