Skip to content

Fix Java 11 compatibility: replace Stream.toList() and use --release flag#322

Merged
Breus merged 1 commit into
masterfrom
fix/java11-stream-tolist-compat
Jun 12, 2026
Merged

Fix Java 11 compatibility: replace Stream.toList() and use --release flag#322
Breus merged 1 commit into
masterfrom
fix/java11-stream-tolist-compat

Conversation

@Breus

@Breus Breus commented Jun 12, 2026

Copy link
Copy Markdown
Owner

Problem

JsonPathParser in the base source set (src/main/java, targeting Java 11) uses Stream.toList(), which was introduced in Java 16. Since the MRJAR only contains META-INF/versions/17/ entries for other classes (not JsonPathParser), the JVM loads the base class on Java 11–15 and throws NoSuchMethodError at runtime.

The root cause is that the build used sourceCompatibility/targetCompatibility instead of --release, which only controls bytecode version but does not enforce API-level compatibility.

Fix

  1. JsonPathParser.java: Replace Stream.toList() (Java 16+) with Collectors.toList() (Java 8+).
  2. build.gradle.kts: Replace sourceCompatibility/targetCompatibility with options.release for both compileJava (11) and compileJava17Java (17). The --release flag tells javac to compile against the target JDK's API surface, so any future use of post-Java-11 APIs in the base source set will fail at compile time.

Verification

  • With only the build.gradle.kts change applied (guard enabled, but .toList() still present), ./gradlew compileJava fails with:
    error: cannot find symbol
        .toList();
        ^
      symbol:   method toList()
      location: interface Stream<JsonPath>
    
  • After applying both changes, ./gradlew clean compileJava passes.

Fixes #320

…flag

Replace Stream.toList() (Java 16+) with Collectors.toList() in
JsonPathParser, which is in the base source set targeting Java 11.

Additionally, replace sourceCompatibility/targetCompatibility with
options.release for both compileJava (11) and compileJava17Java (17).
The --release flag enforces API-level compatibility at compile time,
preventing future use of APIs unavailable in the target Java version.

Fixes #320
@github-actions

Copy link
Copy Markdown

Note

These results are affected by shared workloads on GitHub runners. Use the results only to detect possible regressions, but always rerun on a more stable machine before drawing conclusions!
Regressions/improvements are highlighted when the difference exceeds 3.0%.

Benchmark results

BaselineBenchmark

Method characters jsonSize maskedKeyProbability master (ops/s) PR (ops/s) change master alloc (B/op) PR alloc (B/op) alloc change
regexReplace unicode 1kb 0.1 5,636 4,115 🔴 -27.0% 53,048.4 53,048.6 ⚪ +0.0%
writeFile unicode 1kb 0.1 6,191 5,143 🔴 -16.9% 5,920.4 5,920.5 ⚪ +0.0%
Full results — BaselineBenchmark
Method characters jsonSize maskedKeyProbability master (ops/s) PR (ops/s) change master alloc (B/op) PR alloc (B/op) alloc change
countBytes unicode 1kb 0.1 2,756,194 2,761,493 ⚪ +0.2% 0.0010 0.0010 ⚪ +0.0%
jacksonParseAndMask unicode 1kb 0.1 38,089 39,070 ⚪ +2.6% 58,424.1 58,384.1 ⚪ -0.1%
jacksonParseOnly unicode 1kb 0.1 84,557 85,829 ⚪ +1.5% 17,704.0 17,704.0 ⚪ -0.0%
regexReplace unicode 1kb 0.1 5,636 4,115 🔴 -27.0% 53,048.4 53,048.6 ⚪ +0.0%
writeFile unicode 1kb 0.1 6,191 5,143 🔴 -16.9% 5,920.4 5,920.5 ⚪ +0.0%

InstanceCreationBenchmark

No significant changes (all within 3.0%).

Full results — InstanceCreationBenchmark
Method numberOfTargetKeys master (ops/s) PR (ops/s) change master alloc (B/op) PR alloc (B/op) alloc change
jsonMasker 1000 1,581 1,586 ⚪ +0.4% 1,637,212 1,637,260 ⚪ +0.0%

JsonMaskerBenchmark

Method characters jsonPath jsonSize maskedKeyProbability master (ops/s) PR (ops/s) change master alloc (B/op) PR alloc (B/op) alloc change
jsonMaskerByteArrayStreams unicode true 1kb 0.1 297,690 272,959 🔴 -8.3% 12,184.0 12,184.0 ⚪ +0.0%
jsonMaskerString unicode false 1kb 0.1 227,513 234,346 🟢 +3.0% 10,176.0 10,176.0 ⚪ +0.0%
Full results — JsonMaskerBenchmark
Method characters jsonPath jsonSize maskedKeyProbability master (ops/s) PR (ops/s) change master alloc (B/op) PR alloc (B/op) alloc change
jsonMaskerByteArrayStreams unicode false 1kb 0.1 240,329 235,778 ⚪ -1.9% 10,840.0 10,840.0 ⚪ +0.0%
jsonMaskerByteArrayStreams unicode true 1kb 0.1 297,690 272,959 🔴 -8.3% 12,184.0 12,184.0 ⚪ +0.0%
jsonMaskerBytes unicode false 1kb 0.1 445,366 455,544 ⚪ +2.3% 2,272.0 2,272.0 ⚪ +0.0%
jsonMaskerBytes unicode true 1kb 0.1 423,623 431,898 ⚪ +2.0% 2,024.0 2,024.0 ⚪ +0.0%
jsonMaskerString unicode false 1kb 0.1 227,513 234,346 🟢 +3.0% 10,176.0 10,176.0 ⚪ +0.0%
jsonMaskerString unicode true 1kb 0.1 219,860 215,270 ⚪ -2.1% 10,944.0 10,944.0 ⚪ +0.0%

LargeKeySetInstanceCreationBenchmark

No significant changes (all within 3.0%).

Full results — LargeKeySetInstanceCreationBenchmark
Method keyLength numberOfTargetKeys master (ops/s) PR (ops/s) change master alloc (B/op) PR alloc (B/op) alloc change
jsonMasker 100 1000 132.48 131.69 ⚪ -0.6% 32,372,228 32,372,308 ⚪ +0.0%

StreamTypeBenchmark

Method jsonSize streamInputType streamOutputType master (ops/s) PR (ops/s) change master alloc (B/op) PR alloc (B/op) alloc change
jsonMaskerStreams 1kb ByteArrayStream ByteArrayStream 239,614 249,302 🟢 +4.0% 12,184.0 12,184.0 ⚪ +0.0%
Full results — StreamTypeBenchmark
Method jsonSize streamInputType streamOutputType master (ops/s) PR (ops/s) change master alloc (B/op) PR alloc (B/op) alloc change
jsonMaskerStreams 1kb ByteArrayStream ByteArrayStream 239,614 249,302 🟢 +4.0% 12,184.0 12,184.0 ⚪ +0.0%
jsonMaskerStreams 1kb ByteArrayStream FileStream 5,269 5,158 ⚪ -2.1% 9,176.5 9,176.5 ⚪ +0.0%
jsonMaskerStreams 1kb FileStream ByteArrayStream 92,090 93,742 ⚪ +1.8% 12,304.0 12,336.0 ⚪ +0.3%
jsonMaskerStreams 1kb FileStream FileStream 5,031 5,038 ⚪ +0.1% 9,360.5 9,392.5 ⚪ +0.3%

ValueMaskerBenchmark

Method characters jsonSize maskedKeyProbability master (ops/s) PR (ops/s) change master alloc (B/op) PR alloc (B/op) alloc change
maskWithRawValueFunction unicode 1kb 0.1 597,327 567,293 🔴 -5.0% 1,632.0 1,632.0 ⚪ +0.0%
maskWithStatic unicode 1kb 0.1 662,011 697,147 🟢 +5.3% 1,272.0 1,272.0 ⚪ -0.0%
Full results — ValueMaskerBenchmark
Method characters jsonSize maskedKeyProbability master (ops/s) PR (ops/s) change master alloc (B/op) PR alloc (B/op) alloc change
maskWithRawValueFunction unicode 1kb 0.1 597,327 567,293 🔴 -5.0% 1,632.0 1,632.0 ⚪ +0.0%
maskWithStatic unicode 1kb 0.1 662,011 697,147 🟢 +5.3% 1,272.0 1,272.0 ⚪ -0.0%
maskWithTextValueFunction unicode 1kb 0.1 554,780 569,109 ⚪ +2.6% 1,776.0 1,776.0 ⚪ +0.0%
Raw output (PR @ 517ba4e)
Benchmark                                                           (characters)  (jsonPath)  (jsonSize)  (keyLength)  (maskedKeyProbability)  (numberOfTargetKeys)  (streamInputType)  (streamOutputType)   Mode  Cnt         Score       Error   Units
BaselineBenchmark.countBytes                                             unicode         N/A         1kb          N/A                     0.1                   N/A                N/A                 N/A  thrpt    4   2761493.136 ± 22676.252   ops/s
BaselineBenchmark.jacksonParseAndMask                                    unicode         N/A         1kb          N/A                     0.1                   N/A                N/A                 N/A  thrpt    4     39069.907 ±   622.625   ops/s
BaselineBenchmark.jacksonParseOnly                                       unicode         N/A         1kb          N/A                     0.1                   N/A                N/A                 N/A  thrpt    4     85828.855 ±   703.667   ops/s
BaselineBenchmark.regexReplace                                           unicode         N/A         1kb          N/A                     0.1                   N/A                N/A                 N/A  thrpt    4      4115.069 ±    52.322   ops/s
BaselineBenchmark.writeFile                                              unicode         N/A         1kb          N/A                     0.1                   N/A                N/A                 N/A  thrpt    4      5142.576 ±   139.018   ops/s
InstanceCreationBenchmark.jsonMasker                                         N/A         N/A         N/A          N/A                     N/A                  1000                N/A                 N/A  thrpt    4      1586.256 ±    34.076   ops/s
JsonMaskerBenchmark.jsonMaskerByteArrayStreams                           unicode       false         1kb          N/A                     0.1                   N/A                N/A                 N/A  thrpt    4    235777.955 ±  4041.509   ops/s
JsonMaskerBenchmark.jsonMaskerByteArrayStreams                           unicode        true         1kb          N/A                     0.1                   N/A                N/A                 N/A  thrpt    4    272958.893 ±  6245.934   ops/s
JsonMaskerBenchmark.jsonMaskerBytes                                      unicode       false         1kb          N/A                     0.1                   N/A                N/A                 N/A  thrpt    4    455544.147 ± 11547.242   ops/s
JsonMaskerBenchmark.jsonMaskerBytes                                      unicode        true         1kb          N/A                     0.1                   N/A                N/A                 N/A  thrpt    4    431897.915 ± 10978.066   ops/s
JsonMaskerBenchmark.jsonMaskerString                                     unicode       false         1kb          N/A                     0.1                   N/A                N/A                 N/A  thrpt    4    234345.748 ±  4356.985   ops/s
JsonMaskerBenchmark.jsonMaskerString                                     unicode        true         1kb          N/A                     0.1                   N/A                N/A                 N/A  thrpt    4    215269.504 ± 11560.491   ops/s
LargeKeySetInstanceCreationBenchmark.jsonMasker                              N/A         N/A         N/A          100                     N/A                  1000                N/A                 N/A  thrpt    4       131.694 ±     5.433   ops/s
StreamTypeBenchmark.jsonMaskerStreams                                        N/A         N/A         1kb          N/A                     N/A                   N/A    ByteArrayStream     ByteArrayStream  thrpt    4    249302.336 ±  4466.363   ops/s
StreamTypeBenchmark.jsonMaskerStreams                                        N/A         N/A         1kb          N/A                     N/A                   N/A    ByteArrayStream          FileStream  thrpt    4      5158.051 ±   806.198   ops/s
StreamTypeBenchmark.jsonMaskerStreams                                        N/A         N/A         1kb          N/A                     N/A                   N/A         FileStream     ByteArrayStream  thrpt    4     93742.359 ±   308.433   ops/s
StreamTypeBenchmark.jsonMaskerStreams                                        N/A         N/A         1kb          N/A                     N/A                   N/A         FileStream          FileStream  thrpt    4      5038.221 ±   203.769   ops/s
ValueMaskerBenchmark.maskWithRawValueFunction                            unicode         N/A         1kb          N/A                     0.1                   N/A                N/A                 N/A  thrpt    4    567292.748 ±  3621.804   ops/s
ValueMaskerBenchmark.maskWithStatic                                      unicode         N/A         1kb          N/A                     0.1                   N/A                N/A                 N/A  thrpt    4    697146.718 ± 18375.630   ops/s
ValueMaskerBenchmark.maskWithTextValueFunction                           unicode         N/A         1kb          N/A                     0.1                   N/A                N/A                 N/A  thrpt    4    569109.110 ± 14287.923   ops/s
Raw output (master @ 550a7d4)
Benchmark                                                           (characters)  (jsonPath)  (jsonSize)  (keyLength)  (maskedKeyProbability)  (numberOfTargetKeys)  (streamInputType)  (streamOutputType)   Mode  Cnt         Score       Error   Units
BaselineBenchmark.countBytes                                             unicode         N/A         1kb          N/A                     0.1                   N/A                N/A                 N/A  thrpt    4   2756193.852 ± 19470.219   ops/s
BaselineBenchmark.jacksonParseAndMask                                    unicode         N/A         1kb          N/A                     0.1                   N/A                N/A                 N/A  thrpt    4     38089.269 ±  1377.660   ops/s
BaselineBenchmark.jacksonParseOnly                                       unicode         N/A         1kb          N/A                     0.1                   N/A                N/A                 N/A  thrpt    4     84557.084 ±  1164.167   ops/s
BaselineBenchmark.regexReplace                                           unicode         N/A         1kb          N/A                     0.1                   N/A                N/A                 N/A  thrpt    4      5635.755 ±   160.822   ops/s
BaselineBenchmark.writeFile                                              unicode         N/A         1kb          N/A                     0.1                   N/A                N/A                 N/A  thrpt    4      6190.828 ±  2995.315   ops/s
InstanceCreationBenchmark.jsonMasker                                         N/A         N/A         N/A          N/A                     N/A                  1000                N/A                 N/A  thrpt    4      1580.537 ±    59.714   ops/s
JsonMaskerBenchmark.jsonMaskerByteArrayStreams                           unicode       false         1kb          N/A                     0.1                   N/A                N/A                 N/A  thrpt    4    240328.795 ±  3919.917   ops/s
JsonMaskerBenchmark.jsonMaskerByteArrayStreams                           unicode        true         1kb          N/A                     0.1                   N/A                N/A                 N/A  thrpt    4    297690.391 ±  3369.550   ops/s
JsonMaskerBenchmark.jsonMaskerBytes                                      unicode       false         1kb          N/A                     0.1                   N/A                N/A                 N/A  thrpt    4    445366.379 ±  7859.160   ops/s
JsonMaskerBenchmark.jsonMaskerBytes                                      unicode        true         1kb          N/A                     0.1                   N/A                N/A                 N/A  thrpt    4    423622.566 ±  5563.270   ops/s
JsonMaskerBenchmark.jsonMaskerString                                     unicode       false         1kb          N/A                     0.1                   N/A                N/A                 N/A  thrpt    4    227513.405 ±  1939.585   ops/s
JsonMaskerBenchmark.jsonMaskerString                                     unicode        true         1kb          N/A                     0.1                   N/A                N/A                 N/A  thrpt    4    219859.658 ±  7548.918   ops/s
LargeKeySetInstanceCreationBenchmark.jsonMasker                              N/A         N/A         N/A          100                     N/A                  1000                N/A                 N/A  thrpt    4       132.483 ±    12.011   ops/s
StreamTypeBenchmark.jsonMaskerStreams                                        N/A         N/A         1kb          N/A                     N/A                   N/A    ByteArrayStream     ByteArrayStream  thrpt    4    239613.897 ±  2466.903   ops/s
StreamTypeBenchmark.jsonMaskerStreams                                        N/A         N/A         1kb          N/A                     N/A                   N/A    ByteArrayStream          FileStream  thrpt    4      5269.213 ±   376.554   ops/s
StreamTypeBenchmark.jsonMaskerStreams                                        N/A         N/A         1kb          N/A                     N/A                   N/A         FileStream     ByteArrayStream  thrpt    4     92090.302 ±  2174.854   ops/s
StreamTypeBenchmark.jsonMaskerStreams                                        N/A         N/A         1kb          N/A                     N/A                   N/A         FileStream          FileStream  thrpt    4      5030.899 ±   254.659   ops/s
ValueMaskerBenchmark.maskWithRawValueFunction                            unicode         N/A         1kb          N/A                     0.1                   N/A                N/A                 N/A  thrpt    4    597326.571 ± 37723.266   ops/s
ValueMaskerBenchmark.maskWithStatic                                      unicode         N/A         1kb          N/A                     0.1                   N/A                N/A                 N/A  thrpt    4    662011.055 ±  9631.358   ops/s
ValueMaskerBenchmark.maskWithTextValueFunction                           unicode         N/A         1kb          N/A                     0.1                   N/A                N/A                 N/A  thrpt    4    554780.467 ± 15860.119   ops/s

@sonarqubecloud

Copy link
Copy Markdown

Quality Gate Failed Quality Gate failed

Failed conditions
C Security Rating on New Code (required ≥ A)
B Maintainability Rating on New Code (required ≥ A)

See analysis details on SonarQube Cloud

Catch issues before they fail your Quality Gate with our IDE extension SonarQube for IDE

@Breus Breus merged commit e1783e0 into master Jun 12, 2026
3 of 5 checks passed
@Breus Breus deleted the fix/java11-stream-tolist-compat branch June 12, 2026 10:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Stream.toList() in base classes breaks Java 11 runtime compatibility despite MRJAR and JDK 11 documentation claim

2 participants