应避免创建过多临时对象以减轻堆内存压力和降低gc频次,核心策略是按需复用、延迟创建、控制生命周期;字符串拼接优先用预设容量的stringbuilder,循环中禁用“+”;复用缓冲区与对象池,控制大对象生成节奏,及时释放引用并合理选用引用类型。

避免创建过多临时对象,核心是减少堆内存压力和 GC 频次,尤其在循环、高频调用、字符串操作、大数据处理等场景下效果显著。关键不在于“不用对象”,而在于“按需复用、延迟创建、控制生命周期”。
用 StringBuilder 替代字符串拼接
String 不可变,每次 + 拼接都会生成新对象;高频拼接(如日志组装、SQL 构建、循环内连接)极易产生大量短命对象。
- 循环内必须用
StringBuilder:预估容量(如new StringBuilder(1024)),避免数组多次扩容复制 - 链式调用安全:
sb.append("a").append(i).append(",")全程只操作同一实例,无中间 String - 仅在最终需要时调用
toString(),此前零额外字符串对象 - 单次拼接(如
"Hello " + name)JVM 会自动优化,无需手动改
复用缓冲区与对象池
对固定结构、频繁构造的对象(如 JSON 序列化缓冲、IO 字节数组、DTO 实例),优先复用而非新建。
- 用
ThreadLocal<stringbuilder></stringbuilder>或静态复用实例(注意线程安全),避免每次 new - IO 场景复用
ByteBuffer或 byte[] 数组,配合clear()重置状态 - 对连接、解析器、格式化器等重量级对象,使用成熟对象池(如 Apache Commons Pool、HikariCP 连接池)
- 自定义轻量对象池适用于高并发、构造开销大的 POJO(如消息头、上下文容器)
控制大对象生成节奏
临时大对象(如超长字符串、百万级 List、大 byte[])容易直接进入老年代,诱发 Full GC。
- 禁用全量加载:读取大文件或数据库结果集时,改用流式迭代(
Stream.iterate、JDBCsetFetchSize)、分页/分块处理 - 限制响应体积:接口返回前检查数据规模,超限时截断或报错,避免 Jackson 生成百 MB JSON 字符串
- 禁用无上限缓存:如
static Map<string byte></string>缓存原始文件,须加大小限制 + LRU 清理逻辑 - 设置 JVM 参数
-XX:PretenureSizeThreshold=4194304(4MB),让只有真正超大对象才绕过年轻代
及时释放引用与合理使用引用类型
对象无法被回收,常因“本该失效的引用还被持有”,尤其是静态集合、监听器、缓存、线程局部变量等场景。
- 及时清空集合中无用元素,尤其
static或单例持有的 Map/List - 注册监听器、定时任务、回调后,务必在业务结束时显式注销或移除
- 大对象临时持有者(如处理器、上下文)使用完立即置为
null - 缓存场景酌情使用
WeakReference或SoftReference,让 GC 可在内存紧张时自动回收
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











