On a JMeter .jmx root element, what do the version, properties and jmeter attributes mean?
answer
- Three attributes, one of them read
- One tracks a file in bin
- One records who saved it
- Compatibility comes from a rename map
basics
~10 sThey record the JMX format version, the version of JMeter's save-alias file, and the JMeter build that wrote the file. Only the first is read back, and it barely changes anything.
solid answer
~40 sThe root tag is `<jmeterTestPlan version="1.2" properties="5.0" jmeter="6.0.0">`. `version` is a constant in `SaveService` and has read `1.2` for many releases; `properties` is the `_version` key from `bin/saveservice.properties`, which is `5.0` at JMeter 6.0.0; `jmeter` is the build string of the JMeter that saved the file. On load, JMeter reads **only** `version`, and uses it for one thing: at `1.0` it URL-decodes property values, and at anything else it does not. `properties` and `jmeter` are never read back at all. What actually keeps a ten-year-old plan loading is not the version number but `bin/upgrade.properties`, which maps renamed classes, properties and values forward as the file is parsed.
code
xml · 4 lines<?xml version='1.0' encoding='UTF-8'?>
<jmeterTestPlan version="1.2" properties="5.0" jmeter="6.0.0">
<hashTree>
<TestPlan guiclass="TestPlanGui" testclass="TestPlan" testname="Test Plan" enabled="true">go deeper
Recall that the root tag carries three attributes and that the jmeter one simply records which build saved the file.
Explain that only version is read back, that it matters only at 1.0, and that backward compatibility comes from the alias and upgrade tables instead.
Recognise the header churn and the alias rewrite as review noise, and separate a version migration into a commit of its own.
Decide how the team pins the JMeter version used to author plans, since an unpinned one turns every save into a diff nobody intended.
The first two lines of a `.jmx` look like a compatibility contract. They are mostly a record of what wrote the file. ```xml <?xml version='1.0' encoding='UTF-8'?> <jmeterTestPlan version="1.2" properties="5.0" jmeter="6.0.0"> ``` ## What each attribute is | Attribute | Where it comes from | Read back on load? | |---|---|---| | `version` | A constant in `SaveService`, currently `1.2` | Yes, for one narrow purpose | | `properties` | The `_version` key in `bin/saveservice.properties`, `5.0` at JMeter 6.0.0 | No | | `jmeter` | The running JMeter's own version string | No | The writing side sets all three. The reading side builds a wrapper object that has exactly one field for this header — the version — and the only use it makes of it is to decide whether property values need URL-decoding, which applies at `1.0` and nowhere else. At `1.2` the check is a no-op. `properties` and `jmeter` are informational: nothing consults them, nothing warns on a mismatch. There is a related check that is easy to confuse with this one. At startup JMeter compares the `_version` it read from `bin/saveservice.properties` against the value the code expects and logs a warning if they differ. That is a check on JMeter's own installation, not on your plan file. ## So what actually keeps old plans loading? Backward compatibility is not carried by the version number. It is carried by two lookup tables: 1. **`bin/saveservice.properties`** maps short XML tag names to classes. A class can have several read aliases but only one write alias — for example the HTTP sampler class answers to `HTTPSamplerProxy`, `HTTPSampler` and `HTTPSampler2`, and is always written back as the first of those. 2. **`bin/upgrade.properties`**, applied by `NameUpdater`, renames classes, properties and even property values as the file is parsed. A plan that still says `org.apache.jmeter.assertions.Assertion` is silently read as `ResponseAssertion`. That is why the format version can sit at `1.2` for years while the elements underneath it change completely. ## The part that bites a team Because every save rewrites the whole document, the header is rewritten too, and the `jmeter` attribute is stamped with whoever's build did the saving. Two engineers editing one plan on the same day, one on 6.0.0 and one still on an older install, will conflict on line 2 of the file every single time — a conflict that means nothing and has to be resolved by hand anyway. Worse, the same save rewrites tag names through the write alias. Open a plan whose samplers were stored under an old alias, change one field, save, and every one of those tags is rewritten to the current alias. The diff is enormous and the intended change is one line in the middle of it. ## What to do about it - Pin the JMeter version a team uses to author plans, and note it where the plans live, so the `jmeter` attribute stops churning. - When a plan is being migrated to a newer JMeter, do it as its own commit that changes nothing else, so the alias rewrite is reviewable on its own. - Do not treat the header as a compatibility guarantee. If you need to know whether a plan still works, open it and run it.
- If a JMeter .jmx says jmeter="5.4.1", does JMeter 6.0.0 refuse it or warn about it?Neither. The jmeter attribute is written on save and never read back, so it has no effect on loading. Whether the plan still works depends on the elements it uses and on the rename map in bin/upgrade.properties, not on that string.
- What in JMeter actually lets a plan written years ago still open in JMeter 6?The alias table in bin/saveservice.properties, which maps old tag names to current classes, and bin/upgrade.properties applied by NameUpdater, which renames classes, properties and property values as the file is parsed.
saying these in an interview costs you the question
- Thinks the version attribute gates which elements load
- Says JMeter warns when the jmeter attribute is older
- Believes properties refers to the plan's user variables
- Assumes bumping version in a text editor upgrades a plan
- Treats the header as a compatibility guarantee