Symptom
PasswordHasherSpec: 17 of 24 specs error on Adobe 2025 only (every database leg, matrix run 28815315339):
java.lang.reflect.InaccessibleObjectException: Unable to make public byte[]
com.sun.crypto.provider.PBKDF2KeyImpl.getSalt() accessible: module java.base
does not "opens com.sun.crypto.provider" to unnamed module
Introduced with #3288 (2026-07-06) — this is the only new cross-engine failure from the #2962 feature merges (verified by diffing failing-bundle sets against the 2026-06-28 matrix baseline: Lucee 6/7, Adobe 2023, and BoxLang show no new failures).
Root cause
vendor/wheels/auth/PasswordHasher.cfc ($deriveKey) chains generateSecret(keySpec).getEncoded(). The returned key is a com.sun.crypto.provider.PBKDF2KeyImpl — a JDK-internal class java.base does not open. Adobe 2025's reflection layer makes the concrete class's public methods accessible en masse when dispatching the member call, and its newer JVM rejects that with InaccessibleObjectException (the message names getSalt() because that's the first method the bulk setAccessible trips on). Adobe 2023, Lucee, and BoxLang tolerate the same call — 24/24 there.
Fix
Invoke getEncoded() through the exported javax.crypto.SecretKey interface Method object instead of the concrete class — public interface methods require no opens. PR follows.
Lesson (CLAUDE.md candidate)
Calling members on JDK-internal implementation classes returned by factory APIs (SecretKeyFactory.generateSecret(), Cipher, KeyAgreement results, …) is an Adobe 2025 crash class. Route member calls through the exported interface when the runtime class lives in an unexported com.sun.*/jdk.internal.* package.
Symptom
PasswordHasherSpec: 17 of 24 specs error on Adobe 2025 only (every database leg, matrix run 28815315339):Introduced with #3288 (2026-07-06) — this is the only new cross-engine failure from the #2962 feature merges (verified by diffing failing-bundle sets against the 2026-06-28 matrix baseline: Lucee 6/7, Adobe 2023, and BoxLang show no new failures).
Root cause
vendor/wheels/auth/PasswordHasher.cfc($deriveKey) chainsgenerateSecret(keySpec).getEncoded(). The returned key is acom.sun.crypto.provider.PBKDF2KeyImpl— a JDK-internal classjava.basedoes not open. Adobe 2025's reflection layer makes the concrete class's public methods accessible en masse when dispatching the member call, and its newer JVM rejects that withInaccessibleObjectException(the message namesgetSalt()because that's the first method the bulksetAccessibletrips on). Adobe 2023, Lucee, and BoxLang tolerate the same call — 24/24 there.Fix
Invoke
getEncoded()through the exportedjavax.crypto.SecretKeyinterfaceMethodobject instead of the concrete class — public interface methods require noopens. PR follows.Lesson (CLAUDE.md candidate)
Calling members on JDK-internal implementation classes returned by factory APIs (
SecretKeyFactory.generateSecret(),Cipher,KeyAgreementresults, …) is an Adobe 2025 crash class. Route member calls through the exported interface when the runtime class lives in an unexportedcom.sun.*/jdk.internal.*package.