【lucene】BlockPool 不触发 GC 的秘密 这是一个直击 Lucene 内存管理灵魂的问题。简单来说,IntBlockPool和ByteBlockPool之所以不会触发 GC,是因为它们彻底抛弃了 Java 默认的"按需分配小对象"模式,转而采用"C 语言风格的预分配大数组 + 指针偏移"模式。在标准的 Java 代码中,如果你要存 100 万个变长字节数组,通常会创建 100 万个byte[]对象。每个对象都有对象头、都需要 GC 追踪、都会在堆上产生碎片。而 BlockPool 通过以下三个核心机制消灭了这些问题:1. 大块预分配(Bulk Pre-allocation)BlockPool 从不为单个 Term 或单个 Posting 分配内存。它一次性向 JVM 申请一个固定大小的大数组(例如byte[32768]或int[8192])。GC 影响:无论你在里面写入多少个 Term,JVM 堆上始终只有这一个大数组对象。100 万次写入 = 0 次新对象分配。对比:传统方式下,100 万次写入 = 100 万个短命对象进入 Young Gen,频繁触发 Minor GC。2. 用"整数偏移量"代替"对象引用"这是最关键的一点。在 Pool 内部,没有任何指向子数据的 Object Reference。所有的"指针"都是int类型的偏移量(offset)。// ❌ 传统 Java 方式:每个元素都是一个对象引用,GC 必须扫描 byte[][] postings = new byte[1000000][]; // ✅ BlockPool 方式:只有一个大数组,所有定位靠 int 计算 byte[] pool = new byte[32768]