《Java 高级编程》 · 全书目录与章节索引(34 篇)
《Java 高级编程》全 34 篇,承接卷二 libraryd,深入类型系统、反射与动态代理、类加载与字节码、JMM 与 JUC、虚拟线程与结构化并发、模式匹配、JPMS 与 FFM、JMH 与 JFR:9 章 27 节加序、前言与四个附录的完整索引。
tag
《Java 高级编程》全 34 篇,承接卷二 libraryd,深入类型系统、反射与动态代理、类加载与字节码、JMM 与 JUC、虚拟线程与结构化并发、模式匹配、JPMS 与 FFM、JMH 与 JFR:9 章 27 节加序、前言与四个附录的完整索引。
按进程、线程、堆、JFR、字节码、依赖、运行时裁剪和启动参数八层,给出 libraryd 排障会用到的 jps、jcmd、jstack、jmap、jfr、javap、jdeps、jlink、-Xlog、--enable-preview、--enable-native-access 真实命令、观察点与场景,并逐条标注是否在本机执行。
按 JDK 8/11/17/21/25 五个基线,把 records、sealed、模式匹配、虚拟线程、ScopedValue、FFM、StructuredTaskScope、JEP 491 与 JEP 472 的状态整理成矩阵,逐行标注正式、预览、移除及对 libraryd 的影响,并给出本机验证命令与常见版本误记。
把第 2 章的反射与动态代理整理成可套用模板:三个运行时注解、按实现类查找注解的审计与事务拦截器、Repository<T, ID> 代理工厂、record 组件读取、MethodHandles 替代,以及 InaccessibleObjectException 与模块 opens 处理。
按 libraryd 的借阅计数、事件流水线与仪表盘聚合三条线,整理 volatile、synchronized、ReentrantLock、Condition、原子类、ConcurrentHashMap、六种阻塞队列、同步器、Executors、虚拟线程与 StructuredTaskScope 的关键方法、选型与常见误用,并标注 JDK 25 的预览状态。
JFR 找到热点之后,下一步不是立刻改代码,而是算收益。本节用同一台机器对比 Loan.state 与直接罚金计算的分配采样,用 JMH 量化 synchronized 与 LongAdder 的差距,并比较批量循环与 stream,最后给出 libraryd 的「先测量、再改、再回归」决策表。
JMH 告诉你一次调用多快,JFR 告诉你时间花在哪。本节用 JDK 25 内置 Flight Recorder 记录 10 秒 libraryd 负载,执行 jfr summary、jfr view hot-methods 与 jfr print --events jdk.ExecutionSample,引用 156 个采样和 272 MB Overdue 分配,并说明火焰图边界。
用 System.nanoTime 包一个循环,测出来的往往是 JIT 删除后的空操作。本节用 JMH 1.37 真跑 FinePolicyBenchmark,给出 Warmup、Measurement、Fork 配置和真实结果表,解释 JDK 25 下注解处理器默认关闭导致的 BenchmarkList 缺失,以及为什么 1.8 ns 的差异不能直接当成结论。
FFM 能调用 C,但 native 代码里的空指针会直接带走整个 JVM,try/catch 接不住。本节用真实的 SIGSEGV 崩溃输出说明隔离边界,讨论 Arena 清理、库卸载、跨平台分发与 JNI 迁移成本,并给出 libraryd 在 native 与纯 Java 校验器之间的选择与回退代码。
JNI 需要写头文件、编译胶水代码、处理引用计数。本节用 JDK 25 正式的外函数与内存 API 编译 libisbn,通过 Linker、SymbolLookup 和 MemorySegment 真实调用 isbn13_check_digit,演示 Arena 生命周期与结构体布局,并记录不加 --enable-native-access 时的告警原文。
classpath 上的 libraryd 能编译、能启动,却可能在运行时才暴露缺包和 split package。本节真写 module-info.java,用 jdeps 分析依赖、打成 modular jar,再用 jlink 裁出 32 MB、3 个模块的运行时,并记录缺模块、自动模块名和 classpath 绕过模块描述符的真实输出。
穷尽 switch 只解决了「分支是否齐全」,没有解决 null、守卫顺序和模式嵌套过深。本节用 LoanState 演示 case null 的三种写法、when 守卫的求值规则、模式支配的编译错误,并说明 JDK 25 中 primitive patterns 仍是预览特性,不能带进生产代码。
ErrorCode 枚举加 default 分支的问题不是写法丑,而是新增错误码时编译器不会提醒任何消费方。本节用 LoanState 和 LoanResult 的 sealed 层次演示穷尽 switch,真实编译一次「新增子类型」的失败,并给出 libraryd 中罚金、下一步动作与 HTTP 映射的落地代码。
借阅结果从 service 传到 HTTP 层时,instanceof 加强制转换把类型判断和取值拆成两段。本节用 record pattern 把 LoanResult、LoanState 和嵌套 record 一次解构,讨论未命名模式、守卫与泛型擦除带来的边界,并给出可编译的 libraryd 展示层代码。
虚拟线程让等待变便宜,但不会让连接变多。本节用 400 个任务打 10 个连接的实验说明并发度仍要显式限制,用池化线程上的 ThreadLocal 泄漏演示请求串号,再用 ScopedValue 与令牌桶给出 libraryd 的三件套落地写法。
三个查询扇出,一个 50ms 就失败,另一个却跑满 400ms——invokeAll 不会取消兄弟任务。本节用 JDK 25 预览版的 StructuredTaskScope 把 DashboardService 的三路聚合改成「全成功或全取消」,并实测失败 44ms 返回、超时 106ms 中止。
2000 个虚拟线程只用了 10 个载体线程,同一个虚拟线程睡一觉就换了载体。本节用三个可复现实验拆开挂起、迁移与 pinning,验证 JDK 24 JEP 491 之后 synchronized 不再 pin,而本地调用仍然占住载体,并给出 Javalin 7 的落地配置。
启动预热要等三件事都完成、数据库同时只能进十个任务、分批导出要四个线程每轮对齐。本节用三组真实运行对比 CountDownLatch、Semaphore 与 CyclicBarrier 的语义差异,给出 libraryd 的 StartupGate、DbConcurrencyGate 与 ExportBarrier 实现,以及各自的失效边界。
借阅事件的审计写库不该拖慢请求线程。本节用 ArrayBlockingQueue 搭一条有界流水线,用 300 个事件、32 个槽位、2 个消费者的饱和实验展示背压与拒绝,再把优雅停止做成可观测的 pending、drained、abandoned 三个数。
用 synchronized 包一个 HashMap 也能线程安全,为什么 libraryd 还要换 ConcurrentHashMap?本节用 800 万次原子与非原子写入、三组键规模的对比实验,说明争用点在哪里,再用 CopyOnWriteArrayList 实现借阅监听器,给出两者的适用边界。