在 JDK 17 / 21 / 27 上实测 SecureDirectoryStream:macOS 上只有 JDK 27 的 Files.newDirectoryStream 返回它;JDK 21 上目录被换成符号链接后,检查再使用、toRealPath、已打开的 DirectoryStream 都会删到 outside;JDK 27 上通过流操作删的是原目录;但 walkFileTree 的访问器按路径操作仍会穿过链接,流方法接受 ../ 与绝对路径。
在 JDK 21 / macOS 上用真实的磁盘映像验证 FileStore:APFS、HFS+(20 MB)与 FAT32(64 MB)的类型、容量与属性视图;getFileStores 的 15 项与 mount 对应;写满卷时 usable 与 IOException;FAT32 的 2 秒时间戳;稀疏文件 2 GB 占 0 KB、APFS 克隆不占空间;只读挂载的行为。
在 JDK 21 上用 keytool 生成的三级证书链验证 CertificateFactory:PEM 的前置文字、CRLF、标签文字不检查但头尾要一致;缩进的 PEM、截断的 base64、错位的头尾各自的异常;证书链文件的流语义(连续 4 次调用的第 4 次 Empty input);CertPath 的 PkiPath 与 PKCS7 编码(PKCS7 往返顺序变了);PKIX 验证的顺序与信任锚;同一份 PEM 解析出同一个对象。
在 JDK 21 上用 openssl 现场建 CA、签发与吊销证书,并起真实的 CRL HTTP 服务器与 openssl ocsp 响应器:CRL 过期被当作没有(UNDETERMINED);PKIXRevocationChecker 不需要 enableCRLDP,默认 PKIXParameters 需要;OCSP 每次验证发一次请求;响应器停掉时默认回退到 CRL、NO_FALLBACK 报 UNDETERMINED、SOFT_FAIL 会放行已吊销的证书;2 万条的 CRL 为 707986 字节。
在 JDK 21 上用本机 SSLServerSocket / SSLSocket(RSA-3072 证书)验证 SSLSessionContext:默认缓存 20480 / 超时 86400 秒;默认的会话票据让服务端不缓存会话,setSessionTimeout 与 setSessionCacheSize 都不起作用;关闭 jdk.tls.*.enableSessionTicketExtension 后才生效,缓存 3 个时 6 个客户端按序重连全部完整握手;TLS 1.3 invalidate 一个会话后用另一张票据恢复。
在 JDK 17 / 21 / 27 上验证 KeyGenerator:24 个 SunJCE 服务;AES 默认长度 JDK 17 为 128 位而 JDK 21 / 27 为 256 位;各算法 init(int) 接受的长度与拒绝时的异常(DES 只收 56、HMAC 至少 40 位);随机源由调用者决定,种子固定的 SHA1PRNG 会生成相同的密钥;DES 的奇偶校验位;8 线程共用同一个实例 20 万个密钥无重复。
在 JDK 21 上验证 AlgorithmParameters:34 个服务;GCM 参数编码 19 字节(IV 12 字节 + tag 长度),getEncoded("JSON") 不报错;同一个 Cipher 重用 IV 被拦截,但新建 Cipher 用同一个 IV 不被拦截;CBC 错误的 IV 只破坏第一块;EC 曲线参数的 OID 编码,prime256v1 不被接受;PBE 参数 79 字节含盐、迭代次数与 IV;参数文件与 AAD、篡改的结果。
在 JDK 21 上用自写 LoginModule 与 JDK 自带 KeyStoreLoginModule 验证 JAAS 如何请求口令:PasswordCallback 保存与返回的都是副本,clearPassword 只清内部副本;它可序列化且字节流含口令;required / requisite / sufficient / optional 下 handler 的调用次数与 commit / abort 的调用;共享状态;handler 异常被包装成 LoginException;KeyStoreLoginModule 依次发出的 5 个回调。
在 JDK 21 上用同一个 JVM 里的 SaslClient / SaslServer 验证 SASL:服务端机制只有 DIGEST-MD5、NTLM、CRAM-MD5、GSSAPI,PLAIN 只有客户端,没有 SCRAM / OAUTHBEARER;CRAM-MD5 的响应是确定性的 HMAC-MD5;DIGEST-MD5 的 4 个报文与 rspauth;QOP 与强度协商;auth-int / auth-conf 的 wrap 开销,篡改后的 unwrap 不抛异常而返回空数组。
在 JDK 21 上用本机 HTTP 服务与代理验证 java.net.Authenticator:HttpURLConnection 的凭证按主机缓存、错误口令 20 次后 401、URL 里的 userinfo 不被使用;HttpClient 限制 3 次并抛 IOException,不使用全局 Authenticator;Digest 的 MD5 默认被拒绝(需要 http.auth.digest.reEnabledAlgorithms),HttpClient 不支持 Digest;代理认证的请求者类型 PROXY。
在本机真实的 PostgreSQL 16.15 与 MySQL 26.7.0 上对比 DatabaseMetaData:schema / catalog 的映射(MySQL getSchemas 为 0 个)、getTypeInfo 407 对 44、默认隔离级别 READ_COMMITTED 对 REPEATABLE_READ;supportsBatchUpdates 为 true 但 MySQL 批处理 select 会抛异常;getTables 里 _ 是通配符;getExportedKeys 在 MySQL 返回重复行;2000 张表的查询耗时。
在 PostgreSQL 16.15 与 MySQL 26.7.0 上实测 CallableStatement:PG 驱动默认把 {call …} 翻成 SELECT,调用 PROCEDURE 会失败,需要 escapeSyntaxCallMode=call 或 callIfNoReturn;PG 不支持按名字传参,MySQL 支持;OUT 参数省略、类型登记错误的行为;多结果集与 OUT 参数;refcursor 要 autoCommit=false;MySQL 每次 prepareCall 约 658 µs,复用约 102 µs。