知其然,知其所以然
Java 内部原理 2026-10-04

SQLWarning:数据库的非致命信号

在 PostgreSQL 16.15 与 MySQL 26.7.0 上实测 SQLWarning:PG 的 NOTICE / WARNING 变成 PSQLWarning 挂在 Statement 上,client_min_messages 控制数量,超长字符串直接报错;MySQL 非严格模式下超长、越界、非法日期被静默改写,只留下 4 条警告,且只保留最近一条语句的;严格模式或 jdbcCompliantTruncation=true 抛 MysqlDataTruncation;executeBatch 之后警告丢失。

Java JDBC SQLWarning PostgreSQL MySQL 真实验证 动画演示
Java 内部原理 2026-10-04

SQLXML:在 JDBC 中处理 XML 数据

在 PostgreSQL 16.15(xml 列)与 MySQL 26.7.0(longtext 列)上实测 SQLXML:一次写入限制、XML 声明在 PG 里被去掉、PG 的 xml 列校验而 MySQL 不校验;getSource 对 DOM / SAX 禁用 DOCTYPE,但 StreamSource 配合默认 Transformer 会解析外部实体并读到 /etc/hosts;MySQL 的 StAXSource 抛 NPE、SAXResult 读回缺结束标签;7 MB 文档的读写耗时。

Java JDBC SQLXML XML XXE PostgreSQL MySQL 真实验证 动画演示
Java 内部原理 2026-10-04

JDBC Array 与 Struct:映射数据库复合类型

在 PostgreSQL 16.15 与 MySQL 26.7.0 上实测 JDBC Array / Struct:PG 数组的元素类型与还原(NULL 元素、特殊字符、二维数组)、下标从 1 开始的越界错误;MySQL 不支持 Array / Struct,且 setObject(Integer[]) 会把数组序列化后发给服务器;= ANY(?) 对比 IN 列表(10000 个 id:4.40 对 10.17 ms);PG 复合类型只能通过 PGobject 访问。

Java JDBC Array Struct PostgreSQL 真实验证 动画演示
Java 内部原理 2026-10-04

JDBC 连接池:复用连接也要重置状态

在 PostgreSQL 16.15 与 MySQL 26.7.0 上用 HikariCP 6.2.1 实测:归还时重置了 autoCommit / readOnly / 隔离级别并 rollback 未提交事务,但 SET 会话变量、setSchema / setCatalog、临时表、advisory lock / get_lock 都泄漏给下一个使用者;池耗尽 1 秒后抛异常;泄漏检测;杀掉连接后 500 ms 内再借会拿到坏连接;新建连接约 1.2–1.6 ms,池里借出约 30 µs。

Java JDBC 连接池 HikariCP 连接泄漏 真实验证 动画演示
Java 内部原理 2026-10-04

Servlet 生命周期:实例、线程与请求边界

在嵌入式 Jetty 12.0.16 上实测 Servlet 生命周期:以实例注册的 servlet 启动时全部 init、按类注册的才在第一次请求 init;一个实例处理所有请求(64 并发把非同步 int 的 128000 次加法丢失 186 次);请求对象回收后 getRequestURI 抛 NPE;init 失败后 Jetty 不再重试(第 1 次 500、之后 404);stop 时 stopTimeout 不够会中断请求;异步把 8 个 500 ms 请求从 2041 ms 降到 601 ms。

Java Servlet Jetty 生命周期 线程安全 真实验证 动画演示
Java 内部原理 2026-10-04

Servlet Filter 链:请求如何经过多层处理

在嵌入式 Jetty 12.0.16 上实测 Servlet Filter:链的顺序是声明顺序而不是路径匹配的精确程度、destroy 逆序;不调用 chain.doFilter 的短路与调用两次的后果;请求 / 响应包装;小响应未提交时过滤器在 chain 之后改状态码生效、大响应已提交则被静默忽略;DispatcherType 对 forward / include / error 的作用;异步请求中过滤器的「后」先于请求结束。

Java Servlet Filter 过滤器链 Jetty 真实验证 动画演示
Java 内部原理 2026-10-04

Bean Validation:把约束声明在模型边界

在 Hibernate Validator 8.0.1 上实测 Bean Validation:null 对大多数约束合法、@Email 接受空串;容器元素与 @Valid 级联的路径;@GroupSequence 阻止后组执行;方法验证不会自动拦截直接调用;自定义模板里的 ${...} 不求值但 {key} 仍被插值;验证稳态约 2 µs,而每次新建 ValidatorFactory 约 3.1 ms;Validator 线程安全。

Java Bean Validation Hibernate Validator 约束 真实验证 动画演示
Java 内部原理 2026-10-04

CDI 依赖注入:作用域与代理对象

在 Weld SE 5.1.3 上实测 CDI:@ApplicationScoped / @RequestScoped 注入的是延迟创建的代理(代理上的字段是 null),@Dependent 与 @Singleton 不是代理;final 类 / final 方法 / public 字段无法作普通作用域 bean(启动即报错);拦截器不拦截同类内部调用;@Dependent 循环依赖启动失败;歧义与缺失在启动时报 WELD-001409 / 001408;经代理调用约 77 ns。

Java CDI Weld 依赖注入 作用域 代理 真实验证 动画演示
Java 内部原理 2026-10-04

JUnit 生命周期隔离

在 JUnit Jupiter 上实测测试隔离:默认每个测试方法一个新实例,PER_CLASS 共享一个实例(counter 1、2、3;随机顺序下 6 个种子都有失败);@Nested 每个测试新建外部实例;参数化与重复测试每次调用一个实例;并行执行把 60 万次更新丢失到 319695 且测试仍全部通过;静态状态跨测试类泄漏取决于类的顺序;@TempDir 字段与 static 的区别;被禁用的方法也会构造实例。

Java JUnit 测试隔离 生命周期 并行测试 真实验证 动画演示
Java 内部原理 2026-10-04

Golden Master 测试:保护复杂输出的行为

用一个 17 行的发票文本程序实测 golden master:时间戳与 UUID 让 6 次运行 0 次与 master 一致;de / tr / ar 语言、时区与 file.encoding 改变 16 / 18 / 16 / 4 / 2 行输出,美国西部时区下连 HashSet 顺序都变了;固定 Locale.ROOT 与 UTC、有序集合与占位符后 6 个环境 0 差异;1 行 bug 在加固版里只有 2 行 diff;update=true 会把 bug 写进 master。

Java Golden Master 测试 Locale 时区 确定性 真实验证 动画演示
Java 内部原理 2026-10-04

契约测试:验证 API 双方的共同假设

用 Jackson 2.17.2 与本机 HTTP 服务模拟提供者的 8 个版本:手写桩的消费者测试永远通过,默认 ObjectMapper 打到真实服务上 3 个值正确、3 个抛异常、2 个静默解析出错的值;消费者写的 3 条契约在提供者 CI 里拦住 5 个版本;新增字段、改名、字符串、小数、null、删除字段、新枚举值各自的行为。

Java 契约测试 Jackson API 兼容 消费者驱动 真实验证 动画演示
Java 内部原理 2026-10-03

HotSwap:为什么调试时只能改部分方法体

用 Instrumentation.redefineClasses 逐一验证热替换的限制:只改方法体(含 static)成功;新增/删除方法、新增字段、改签名、改修饰符、改继承关系都抛 UnsupportedOperationException;已有实例立即用新方法体、字段值保持;正在栈上执行的那次调用跑完旧代码。

Java HotSwap 热替换 Instrumentation redefineClasses 真实验证 动画演示
京ICP备2026067502号-1京公网安备11010502063487号