Repository navigation
Ship the Java 10 shim in META-INF/versions/10 so Java 8 builds accept the jar - #516
Conversation
Since 20260921.1 bundled the shims into the sanitizer jar, its root held two classes compiled for Java 10, org.owasp.shim.ForJava10AndLater and the empty org.owasp.shim.Notice. A Java 8 project that checks its dependencies with the Maven Enforcer rule enforceBytecodeVersion at maxJdkVersion 1.8 failed on the jar unless it listed both in ignoreClasses. java10-shim now compiles ForJava10AndLater a second time, into META-INF/versions/10/, and the shade configuration takes only that copy from the module. The jar is already multi-release for its module descriptor, so Java 10 and later find the shim there and Java 8 and 9, like the enforcer rule, never look. The root copy stays in java10-shim's own output because the reactor's test class paths read it from a directory, where versioned entries do not apply, so `mvn test` and `mvn verify` still run the same shim. src/it/java8-consumer is a Java 8 program the build runs against the packaged jar at integration-test. It fails if any class is newer than Java 8 outside META-INF/versions/, or newer than N inside META-INF/versions/N/, or if the sanitizer does not pick the shim meant for the running JDK. On the old jar it names the two Java 10 classes; on a jar without the Multi-Release header it reports the Java 8 fallback on Java 21. A new CI job packages with JDK 11 and runs it on a Java 8 runtime, the first time CI loads the jar on Java 8. Closes #515. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Java 8's javac fails with 'directory not found' when the -d directory does not exist; later javac versions create it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The bnd comment on the Multi-Release header said the jar is multi-release only for its module descriptor and holds no versioned class. Since the previous commits it also holds ForJava10AndLater in META-INF/versions/10/, and without the header every runtime falls back to ForJava8. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Java8ConsumerCheck checked that Sanitizers and Java8Shim came from the jar under test, but not the shim Java8Shim picked, which is the class the versioned directory exists for. With java10-shim/target/classes ahead of the jar on the class path the check passed, on the root copy of ForJava10AndLater, and now fails: org.owasp.shim.ForJava10AndLater loaded from .../java10-shim/target/classes The build and CI put nothing else on the class path, so no run so far was affected. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The shade filter named META-INF/versions/10/, while java10-shim's release comes from maven.compiler.release. Had that property moved, the versioned compile would have landed elsewhere and the filter would have silently shipped no shim; only Java8ConsumerCheck's selection check would have noticed. Take META-INF/versions/** instead. The shaded jar is unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
JpmsConsumerCheck now loads ForJava10AndLater, uninitialized, through the sanitizer module's class loader on Java 10 and later and checks it is in that module, so the build shows the versioned entry is read on the module path as well as on the class path. A copy of the jar without META-INF/versions/10/ fails with the module has no ForJava10AndLater on Java 21 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
'A `ignoreClasses` workaround' becomes 'An'. The change log and docs/maven.md said enforceBytecodeVersion allows the versioned shim; it does so in its default mode, and with strict set it holds versioned classes to maxJdkVersion too, so say so. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Review passAn independent review (verdict: merge after small fixes) found nothing functional wrong. It raised one should-fix and five nits. Each is fixed in its own commit:
The review also checked, by running them: the shaded jar's entries and dependency-reduced POM, the reporter's real enforcer rule, shim selection on JDK 11/17/21 in four class-path and module-path shapes, After the fixes, 🤖 Generated with Claude Code |
Problem
Since 20260921.1 bundled the shims into the sanitizer jar, its root has held two classes compiled for Java 10:
org.owasp.shim.ForJava10AndLaterand the emptyorg.owasp.shim.Notice. A Java 8 project that checks its dependencies with the Maven Enforcer ruleenforceBytecodeVersionatmaxJdkVersion1.8 fails on the jar unless it lists both inignoreClasses(#515).Fix
java10-shim/pom.xml: a second compiler execution compilesForJava10AndLaterintotarget/classes/META-INF/versions/10/.java10-shimit takes onlyMETA-INF/versions/10/**. The jar is alreadyMulti-Release: truefor its module descriptor, so Java 10+ finds the shim there, while Java 8 and 9 never look. The enforcer rule doesn't look there either: it allows release N underMETA-INF/versions/N/(source).Noticeis no longer shipped.java10-shim's own output. Withmvn test, the reactor's test class paths read that module from a directory, where versioned entries don't apply. Keeping the root copy meansmvn testandmvn verifystill run the same shim, whichexamples/pom.xmlrelies on.Notice.javastays in the source tree. It isjava10-shim's only public class, and thepublicationprofile builds Javadoc for every module.Which shim each runtime uses is unchanged:
ForJava8(the class fails to load)ForJava8(the class isn't visible)ForJava8ForJava8ForJava10AndLaterForJava10AndLaterThe one difference is in setups that ignore multi-release jars, such as OSGi frameworks before R7 or a consumer's repackaged jar that drops the header. On any Java version, those now use
ForJava8, the implementation Java 8 users already run.Regression checks
src/it/java8-consumer/Java8ConsumerCheckis a Java 8 program thatverifycompiles and runs against the packaged jar on the class path atintegration-test, next to the JPMS consumer. It fails if:META-INF/versions/is newer than Java 8, or any class underMETA-INF/versions/N/is newer than N;java8-runtime, packages with JDK 11 and runs the same check on a Java 8 runtime. Until now CI never loaded the jar on Java 8.Verification
./mvnw -o -ntp -B clean verifypasses on JDK 11, 17, 21 and 25. On each, the check reports 140 classes within bounds andForJava10AndLaterselected.org/owasp/shim/ForJava10AndLater.class is compiled for Java 10 but is outside META-INF/versions/, and the same forNotice.class.enforceBytecodeVersion,maxJdkVersion1.8, noignoreClasses, extra-enforcer-rules 1.10.0) fails on the released 20260924.2 jar and passes on this branch's jar.Multi-Releaseheader removed fails the check on JDK 21 (loaded org.owasp.shim.ForJava8 rather than org.owasp.shim.ForJava10AndLater). So a silent fallback can't slip through.Also updated:
change_log.md(adds a* Next releaseentry),docs/maven.md, thejava10-shimand library READMEs, the loader comment inJava8Shim, and one rule inAGENTS.md: every class outsideMETA-INF/versions/must be Java 8 bytecode.Closes #515
🤖 Generated with Claude Code