核心是让对象“少创建、多复用、早清理”,优先外提循环内对象(如StringBuilder),使用前重置、避免跨线程共享、作用域结束置null;谨慎评估对象池适用条件;高并发推荐ThreadLocal栈或平台优化池;复用必重置状态并设上限监控。

核心是让对象“少创建、多复用、早清理”,不靠堆大小硬扛,而是从源头控制短命对象生成。
优先外提循环内对象
这是见效最快、成本最低的手段。只要对象可复用、无状态残留、且在单线程或线程安全前提下,就该提到循环外。
- 适合外提的典型对象:StringBuilder、ByteBuffer、ByteArrayOutputStream、ArrayList、HashMap(每次用前必须 clear())
- 必须同步做三件事:使用前重置(如 sb.setLength(0))、避免跨线程共享非线程安全对象(如 SimpleDateFormat 要套 ThreadLocal)、作用域结束及时置 null(尤其大数组)
- 错误示范:循环里 new StringBuilder();正确做法:循环外声明 + 每次 setLength(0)
谨慎评估是否上对象池
对象池不是万能解药,用错反而加重 GC 压力。只在满足三个条件时才考虑:
- 对象生命周期可预测(比如网络请求响应体、游戏中的子弹)
- 单次构造开销大(new + 初始化 >100ns),且每秒创建超千次
- 逃逸分析失效(通过 -XX:+PrintEscapeAnalysis 或 JFR 确认对象大量逃逸出方法)
- 小对象(如 Point、简单 DTO)优先走 TLAB 分配,池化反而绕过 JVM 优化
选对复用结构,避开并发瓶颈
高并发下共享池容易成为锁热点,更推荐轻量隔离方案:
立即学习“Java免费学习笔记(深入)”;
- 用 ThreadLocal<Stack<T>> 实现线程独占栈,pop/push 零同步开销
- 数组类对象(如 byte[1024])优先用平台优化实现:Java 可参考 Netty 的 PooledByteBufAllocator,Android 直接用 Message.obtain()
- 避免链表式池管理中隐式 GC 风险,归还必须显式 recycle() 或 reset()
严格管控复用对象的状态与生命周期
复用不等于“扔进去就完事”,状态污染和内存泄漏往往源于归还环节疏忽:
- 归还前必须执行 resetFn:清空集合、置 null 引用、还原 flag、重置内部缓冲区
- 设 maxSize 上限(如预加载 20 个,动态扩容单次 ≤5 个),防突发流量撑爆堆
- 监控对象存活时间,超时未归还的记录日志或强制回收,避免“幽灵对象”滞留


















