在 JDK 21 上实测安全审计日志:-Djavax.net.debug=ssl:record:plaintext 会把请求头与口令的明文写进日志;URL / URI / HttpRequest / Properties / char[] 的打印与 JDK 异常消息会带出口令;哈希链能发现篡改、删除与交换,但发现不了尾部截断与整条重算,HMAC 链加外部锚点才可以;JFR 的 TLS / X509 事件只含动作不含秘密。
在 Hibernate 6.6.4 + 真实 PostgreSQL 上实测持久化上下文:改托管实体的字段不用调用任何 save 就会在 commit 时发出(包含所有列的)UPDATE;同一 EntityManager 里同一主键是同一个对象;detach 后的修改不保存、merge 返回新的托管对象;AUTO 模式下查询前先 flush;托管实体 5 万个时无修改的 flush 也要 3.7 ms。
在 Hibernate 6.6.4 + 真实 PostgreSQL 上实测 JPA 实体生命周期:persist(游离对象)抛 EntityExistsException、对 removed 对象再 persist 回到 managed;@PostPersist 在 IDENTITY 下是 persist 时、在 SEQUENCE 下是 flush 时;@PostUpdate 里的修改要靠第二条 UPDATE 保存;@PreUpdate 里执行查询会递归 flush 478 次、发出 951 条 SQL;@PrePersist 抛异常后 commit 静默回滚。
在 Hibernate 6.6.4 + 真实 PostgreSQL 上实测 JPA 一级缓存:只有 find / getReference 命中缓存,所有 JPQL 都发 SQL,但返回的是缓存里的旧实体(另一个连接已改成 99 仍看到 30);只改 name 的提交会把别人写的 age 覆盖回旧值;读 10 万行不清理缓存堆内存 +82 MiB,每 1000 个 clear 或 StatelessSession 为 +0。
在 Hibernate 6.6.4 + 真实 PostgreSQL 上实测 JPA 乐观与悲观锁:@Version 的 UPDATE 带 where version = ?,冲突抛 OptimisticLockException;PESSIMISTIC_WRITE 是 for no key update,nowait / skip locked 可用,但大于 0 的锁超时被忽略;死锁约 1 秒后检测并被包装成 OptimisticLockException;8 线程计数器:无锁丢失 1347 / 1600 次,乐观重试 6216 次,悲观最快。
在 Hibernate 6.6.4 + 真实 PostgreSQL 上实测 JPA Criteria API:与 JPQL 发出同样的 SQL(值是绑定参数,cb.literal 才内联);字符串属性名拼错与类型错误在运行时才报错,静态元模型把拼写错误提前到编译期;每次重新构建比 JPQL 慢约 25%(77.0 vs 61.5 µs)且不经过查询计划缓存;8 种动态条件组合产生 8 种 SQL 文本。
在 Hibernate 6.6.4 + 真实 PostgreSQL 上实测 AttributeConverter:autoApply 也应用到基本类型 boolean;转换器要自己处理 null,空集合存成空串;原地修改被转换的 Set 能被脏检查发现;加载 1000 个实体 toEntity 被调用 3000 次;参数与字面量都会转换,like 不能用在被转换的字段上;库里出现无法识别的值会让读到它的查询失败。
在 Hibernate 6.6.4 + 真实 PostgreSQL 上实测 JPA N+1:1000 个作者逐个访问 books 是 1001 条 SQL(201.5 ms);@ManyToOne 默认 EAGER 让 JPQL 也 N+1;join fetch / EntityGraph / DTO 为 1 条 SQL,@BatchSize 41 条,SUBSELECT 2 条;两个 List 同时 fetch 抛 MultipleBagFetchException,Set 得到 20000 行的笛卡尔积;带集合 fetch 的分页在内存里读入 6000 个实体。
用 Jersey 3.1.9 + JDK HTTP 服务器实测 JAX-RS 过滤器:请求过滤器按 @Priority 升序、响应过滤器降序;@PreMatching 能改写路径与方法;abortWith 跳过资源但响应过滤器照常运行;过滤器抛出的异常经 ExceptionMapper 映射成 500;过滤器读取请求体不放回会让资源收到空 body。
用嵌入式 ActiveMQ Artemis 2.37.0 实测 JMS 确认模式:AUTO_ACKNOWLEDGE 在 receive() 返回时确认,消费者崩溃会丢消息;CLIENT_ACKNOWLEDGE 的 acknowledge() 确认会话已收到的全部消息;监听器抛异常会重新投递;事务会话 rollback 立刻重新投递,生产者事务 commit 才可见;超过最大投递次数进入死信队列,但死信队列不存在时消息直接消失。
用 Jetty 12.0.16 的 Jakarta WebSocket 服务端与 JDK 客户端实测 Endpoint 生命周期:每个连接一个实例,@OnOpen → @OnMessage → @OnClose;abort 得到 @OnError + 1006;@OnMessage 抛异常得到 CloseException 与 1003;空闲 804 ms 后 1001;100,000 字符超过默认 64 KiB 得到 1009;并发 sendText 在 Jetty 上不报错。
用 JUnit 5.11.3 实测 @Nested:每个测试重新构造整条外 → 内的实例链,5 个测试共 10 次 @BeforeEach、10 次构造;控制台启动器不能直接选择嵌套类(--select-class / --select-method 都是 0 个测试,--include-classname 只对顶层类生效);没有 @Nested 的静态嵌套类在选择外层类时不运行;@ExtendWith、@Tag、@Disabled 向内层继承。