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

Netty 粘包拆包:TCP 为什么没有消息边界

真实验证 TCP 没有消息边界:50 字节 × 2000 次写入被合并成 855 次 read(平均 116 字节),20000 字节的消息被拆成不整的读取 34 次;Netty 不加解码器时 2000 条消息只触发 50 次 channelRead,加 LengthFieldBasedFrameDecoder / LineBasedFrameDecoder / FixedLengthFrameDecoder 后恰好 2000 次。

Java Netty TCP 粘包拆包 真实验证 动画演示
Java 内部原理 2026-10-02

Java 序列化:一个对象如何变成字节流

真实验证 Java 序列化:71 字节的流里只有 7 字节数据,其余是魔数与类描述;transient/static 不进流、字段初始化器不运行、不可序列化父类的无参构造器被调用;共享引用被保留;没有显式 serialVersionUID 时加一个字段就让旧数据读取失败,显式声明后读取成功但新字段是 null。

Java 序列化 Serializable serialVersionUID 真实验证 动画演示
Java 内部原理 2026-10-02

Lambda:invokedynamic 如何生成函数对象

javap 与运行时验证 lambda 的实现:lambda 没有类文件、函数体变成私有静态合成方法加一条 invokedynamic(引导方法 LambdaMetafactory.metafactory);不捕获变量的 lambda 是同一个对象、捕获变量的每次求值新建;运行时类是隐藏类 Main$$Lambda/0x…;第一个 lambda 位置首次求值约 3 ms,多加载 90 个类。

Java Lambda invokedynamic 字节码 真实验证 动画演示
Java 内部原理 2026-10-02

Stream:惰性求值、流水线和短路操作

用带日志的流水线验证 Stream 的执行方式:没有终结操作什么都不发生;每个元素依次走完整条流水线;sorted() 是屏障;limit/findFirst/anyMatch 让无限流或百万元素流只处理很少的元素;limit 的位置改变上游产生的元素数;大小已知时 count() 会跳过 peek 与 map(JDK 17、21、27 一致)。

Java Stream 惰性求值 短路 真实验证 动画演示
Java 内部原理 2026-10-02

StampedLock:乐观读到底是不是真正无锁

真实验证 StampedLock:乐观读只拿版本号、写锁期间与写锁之后旧 stamp 都失效;验证之前确实会读到 x+y≠100 的数据(2417 次),validate 通过后 0 次;8 个读线程下乐观读 2756 百万次/秒,读锁只有 1.9~2.4;不可重入。

Java StampedLock 乐观读 并发 真实验证 动画演示
Java 内部原理 2026-10-02

虚拟线程:Java 21 如何让一个线程对应一个任务

JDK 21 虚拟线程实测:10000 个各 sleep 1 秒的任务,虚拟线程 1073 ms 完成、RSS 85 MB;每任务一个平台线程在第 4059 个任务时因 unable to create native thread 失败;200 线程池要 50358 ms;纯计算任务虚拟线程没有优势;2000 个虚拟线程只用了 10 个载体线程。

Java 虚拟线程 Java 21 并发 真实验证 动画演示
Java 内部原理 2026-10-02

虚拟线程 Pinning:什么情况下仍然会卡住载体线程

载体线程限制为 2 个时,10 个虚拟线程各阻塞 500 ms:JDK 21 上 synchronized 里阻塞要 2548 ms(被固定、分 5 批),ReentrantLock 与无锁都只要约 520 ms;JDK 27 上三种都约 519 ms;用 -Djdk.tracePinnedThreads=full 看固定发生的栈。

Java 虚拟线程 pinning synchronized 真实验证 动画演示
Java 内部原理 2026-10-02

CompletableFuture 超时与取消:任务到底能不能停

真实验证 CompletableFuture 的超时与取消:orTimeout 超时后任务从 4 步继续跑到 15 步,cancel(true) 不中断任务,依赖阶段抛 CompletionException(cause 为 CancellationException);executor.submit 的 Future.cancel(true) 才能中断任务,并可与 CompletableFuture 组合;completeOnTimeout 与 get(timeout) 的语义差别。

Java CompletableFuture 超时 取消 并发 真实验证 动画演示
Java 内部原理 2026-10-02

反射与 MethodHandle:一个方法调用如何变成调用点

真实验证 MethodHandle:invokeExact 的类型必须完全一致、invoke 自动适配、bindTo 绑定接收者、访问检查在查找时发生;static final 的 MethodHandle 与直接调用一样快(0.31 ns),放在非 final 字段里慢到 2.34 ns,Method.invoke 是 2.76 ns。

Java MethodHandle 反射 invokeExact 真实验证 动画演示
Java 内部原理 2026-10-02

动态代理:JDK Proxy 和代理调用链怎么生成

真实验证 JDK 动态代理:代理类是 public final 的 jdk.proxy1.$ProxyN,toString/hashCode/equals 也进 handler;handler 里直接 m.invoke 会让目标的 IOException 变成 UndeclaredThrowableException;default 方法要 invokeDefault;代理调用约 3.28 ns(直接 0.35 ns);并把生成的代理类导出来看字节码。

Java 动态代理 Proxy InvocationHandler 真实验证 动画演示
Java 内部原理 2026-10-02

注解:Retention、反射和运行时代理

真实验证注解的运行时形态:注解实例是 $ProxyN 代理对象、同一注解读两次是同一对象;@Inherited 只沿父类继承,接口和方法注解不继承;重复注解被包进容器后 getAnnotation 读到 null;CLASS/SOURCE 读不到;TYPE_USE 注解要走 getAnnotatedType;第一次 getAnnotation 约 12 ms;并用 javap 看注解在类文件里的位置。

Java 注解 反射 Inherited Repeatable 真实验证 动画演示
Java 内部原理 2026-10-02

ServiceLoader:Java SPI 如何发现实现类

真实验证 ServiceLoader:META-INF/services 里的顺序就是迭代顺序、load 与 stream 不实例化、迭代时才构造并缓存、reload 清缓存;配置出错在迭代到该项时抛 ServiceConfigurationError;模块方式用 provides/uses,module-path 里没有 impl 时找不到实现也不报错。

Java ServiceLoader SPI 模块系统 真实验证 动画演示
京ICP备2026067502号-1京公网安备11010502063487号