skip to content

Packaged Extensions

Behaviour that arrives as a JAR on the classpath rather than as script text in the plan, and the install, versioning and portability questions that come with anything outside the stock download.

on this pageshow

explore

questions

6

In Apache JMeter, which directory does a third-party plugin JAR go in, and which one takes its dependencies?

level: juniorimportance: must knowfreq 71%

answer

  1. Two directories, two different jobs
  2. One of them is scanned; one is not
  3. Dependencies must not sit beside plugins
  4. Only files ending .jar, no sub-directories

basics

~10 s

The plugin JAR itself goes in JMETER_HOME/lib/ext. The utility and dependency JARs it needs go in JMETER_HOME/lib. Only lib/ext is scanned for new JMeter components, and only files ending in .jar are picked up.

solid answer

~40 s

Drop the plugin's own JAR - the one holding the sampler, listener, timer or GUI classes - into `JMETER_HOME/lib/ext`, and every library it depends on into `JMETER_HOME/lib`. JMeter's launcher puts the `.jar` files sitting directly in `lib`, `lib/ext` and `lib/junit` onto the classpath at startup, so all three are *loadable*; the difference is that only `lib/ext` (plus whatever the `search_paths` property adds) is *scanned* for JMeter components, which is how a plugin's elements reach the Add menus. The manual is explicit that `lib/ext` is not for utility or dependency jars. Three details bite: JARs in sub-directories are ignored, files that are not `.jar` are ignored, and setting the `CLASSPATH` environment variable achieves nothing because `bin/jmeter` starts the JVM with `java -jar`. Restart JMeter after adding a JAR.

code

text · 15 lines
text
apache-jmeter-6.0.0/
  bin/
    jmeter.properties
    user.properties
  lib/
    postgresql-42.7.4.jar          <- dependency the plugin needs
    cmdrunner-2.3.jar
    ext/
      ApacheJMeter_core.jar
      jmeter-plugins-manager-2.0.jar   <- plugin JAR
      jmeter-plugins-dummy-0.4.jar     <- plugin JAR
      mystuff/
        ignored.jar                  <- never loaded: sub-directory
    junit/
      my-junit-tests.jar

go deeper

for a junior

Remember the pair: the plugin JAR goes in lib/ext, the libraries it needs go in lib, and you restart JMeter afterwards.

for a middle

Explain that all three shipped directories reach the classpath but only lib/ext is scanned for components, which is why a plugin in lib loads yet never appears in the menus.

for a senior

Show that you provision lib and lib/ext deliberately - image layer, checked-in directory or install script - because a .jmx names plugin classes and will not open without them.

for a principal

Own the policy: who may add a JAR to a shared injector, how the contents are versioned and reproduced, and what the scan cost of a bloated lib/ext buys the team.

Apache JMeter 6.0.0 ships no plugin registry, no manifest to edit and no install command in the Apache download. Installing a third-party plugin means putting a JAR file in the right directory and restarting, so getting the directory wrong is the commonest reason a freshly downloaded plugin "does not appear". ## The three directories JMeter reads at startup `NewDriver`, the class `bin/jmeter` actually launches, builds JMeter's classloader before any other JMeter code runs. It looks in exactly three places under `JMETER_HOME`: - **`lib`** - utility and dependency JARs: JDBC drivers, messaging client libraries, and every library a plugin needs but does not bundle inside itself. - **`lib/ext`** - JMeter components and plugins: the JAR that contains samplers, listeners, timers, controllers, assertions, config elements and their GUI classes. - **`lib/junit`** - JARs holding the JUnit `TestCase` classes that the JUnit Request sampler drives. Every `.jar` found **directly** in those directories is added, sorted by name so the order is predictable across machines. Sub-directories are not walked, and anything that is not a `.jar` is skipped without comment - the manual notes that JMeter will only find `.jar` files, not `.zip`. ## Loadable is not the same as discoverable Because all three directories land on the classpath, a plugin JAR technically *loads* from any of them. What makes `lib/ext` special is discovery. `JMeterUtils.getSearchPaths()` returns `JMETER_HOME/lib/ext` first, followed by whatever the `search_paths` property adds, and that array is the search path JMeter's class finder walks when it builds the list of components it is able to offer. A component JAR dropped into `lib` sits on the classpath and can still be named explicitly, but nothing scans it, so its elements never appear in the tree's Add menus. The reverse mistake costs you as well. The manual says plainly that you should not use `lib/ext` for utility jars or dependency jars used by the plugins, because it is only intended for JMeter components and plugins. Piling a plugin's transitive dependencies into `lib/ext` turns every one of them into a candidate for the component scan on every startup: pure cost, no benefit. | Directory | What belongs there | On the classpath | Scanned for components | |---|---|---|---| | `lib` | utility and dependency JARs | yes | no | | `lib/ext` | plugin and component JARs | yes | yes | | `lib/junit` | JUnit `TestCase` JARs | yes | by the JUnit Request class chooser | ## The rules that trip people up 1. **`CLASSPATH` does nothing.** JMeter is started with `java -jar`, and the `java` command silently ignores both the `CLASSPATH` environment variable and the `-classpath`/`-cp` options when `-jar` is used. This is a Java rule, not a JMeter quirk, and the manual calls it out for exactly that reason. 2. **A restart is required.** The classloader is built and the component scan runs once, during startup. Copying a JAR into `lib/ext` while JMeter is open changes nothing until you relaunch it. 3. **Only `.jar`.** A directory of loose `.class` files, or a `.zip`, is invisible to the launcher. 4. **No recursion.** `lib/ext/mystuff/plugin.jar` is not found; `lib/ext/plugin.jar` is. 5. **A missing dependency reads like a broken plugin.** The plugin's element may appear in the menu, then fail with a `NoClassDefFoundError` the moment it runs, because its library never made it into `lib`. ## When you cannot write into the installation A locked-down or shared JMeter installation is common, and three properties in `bin/jmeter.properties` exist for it: `search_paths` adds directories to the component search path alongside `lib/ext`, while `user.classpath` and `plugin_dependency_paths` add directories of dependency JARs alongside `lib`. All three are shipped commented out, so none of them is set unless you set it. ## Why this outlives the first install An injector's `lib/ext` is part of a test plan's contract, not a local convenience. A `.jmx` records the fully qualified class name of every element it uses, so a plan authored on a workstation that has a plugin installed is unopenable on a machine that does not. Treat the contents of `lib` and `lib/ext` as something you provision deliberately - a container image layer, a checked-in directory, or a scripted install step - rather than something a person copies once and forgets.

  • What is JMETER_HOME/lib/junit for, and how does it differ from lib/ext?
    It is where the JUnit Request sampler expects the JARs holding your JUnit test classes. Its class chooser scans `lib/junit` plus any directories named by the `user.classpath` property for classes extending JUnit's `TestCase`, whereas `lib/ext` is scanned for JMeter's own component types such as samplers and listeners.
  • Why does exporting CLASSPATH before running bin/jmeter not make a plugin visible?
    Because `bin/jmeter` launches the JVM with `java -jar`, and `java` silently ignores the `CLASSPATH` environment variable and the `-classpath`/`-cp` options whenever `-jar` is used. Put the JAR in `lib` or `lib/ext`, or point the `user.classpath` or `search_paths` property at the directory holding it.

saying these in an interview costs you the question

  • Says exporting CLASSPATH makes JMeter find the plugin JAR
  • Puts a plugin's dependency jars into lib/ext beside the plugin
  • Expects JMeter to recurse into sub-directories of lib/ext
  • Thinks a zip of classes in lib/ext will be loaded
  • Assumes a new jar is picked up without restarting JMeter
open as a page

A JMeter plan using a jp@gc element runs locally but dies on a clean CI checkout before any sample. Why?

level: seniorimportance: must knowfreq 57%

basics

~20 s

The .jmx names the plugin's Java class, and the CI agent has no plugin jar in lib/ext. JMeter cannot resolve that class while parsing the plan, so the run aborts at load and writes no results file.

open as a page

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

level: middleimportance: should knowfreq 41%

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.

open as a page

In JMeter's Java Request sampler, which interface must your class implement and when is each method called?

level: middleimportance: should knowfreq 47%

basics

~10 s

The class must implement org.apache.jmeter.protocol.java.sampler.JavaSamplerClient. JMeter calls setupTest once before the first sample, runTest for every sample, teardownTest at the end, and getDefaultParameters to populate the sampler's argument table.

open as a page

How would you govern the third-party JMeter plugins a team's test plans are allowed to depend on?

level: principalimportance: should knowfreq 38%

basics

~20 s

Treat the plugin set as part of the injector, not the plan: a pinned, reviewed list provisioned the same way everywhere. Decide per plugin whether it earns the coupling, and prefer JMeter's built-in hooks when it does not.

open as a page

What must a compiled custom JMeter function declare for JMeter to discover it?

level: seniorimportance: nice to knowfreq 26%

basics

~20 s

It must implement JMeter's Function interface, normally by extending AbstractFunction, and return its name from getReferenceKey. Register it in META-INF/services so JMeter's service lookup finds it; otherwise it is only found by a scan of lib/ext and the directories search_paths names.

open as a page