「Java 佔內存」多半是代碼陋習所致。本文提煉 9 條內存管理鐵律,涵蓋對象創建、集合使用、引用管理、IO 資源釋放,助你從源頭消除內存洩漏與壓力。
new Boolean()、new Integer() —— 用靜態工廠方法痛點:大量小對象撐爆堆。Boolean 只有 TRUE/FALSE 兩個實例,Integer 緩存 -128~127。
// ❌ 反模式
ps.setBoolean("flag", new Boolean(true));
List<Integer> ids = new ArrayList<>();
for (int i=0; i<10000; i++) ids.add(new Integer(i)); // 10000 個對象
// ✅ 最佳實踐
ps.setBoolean("flag", Boolean.TRUE); // 或 Boolean.valueOf(true)
ids.add(Integer.valueOf(i)); // 命中緩存,極大減少對象數
原則:所有包裝類優先用 valueOf(),基本類型優先用基本類型(int 而非 Integer)。
StringBuilder(單線程)或 StringBuffer(多線程)// ❌ 循環拼接產生 N 個 String 對象
String sql = "SELECT * FROM t WHERE ";
for (String col : cols) sql += col + "=?, ";
// ✅ 單個 StringBuilder
StringBuilder sb = new StringBuilder("SELECT * FROM t WHERE ");
for (String col : cols) sb.append(col).append("=?, ");
String sql = sb.toString();
日誌框架(SLF4J/Log4j2)已內建懶評估,避免無效拼接:log.debug("user={}, order={}", user, order)。
無界 HashMap 緩存 = 內存洩漏定時炸彈。必須引入成熟緩存框架:
配置關鍵參數:maximumSize、expireAfterWrite、weakKeys/weakValues。
StackOverflowError,且 JIT 內聯優化失效。核心熱點方法控制在 10 層以內。byte[]、BufferedImage)用完立即賦 null 或縮小作用域。static 引用大對象/集合static 字段生命周期 = 類加載器生命周期,通常等於應用壽命。常量用 static final,可變狀態絕不 static。單例模式改用 Spring Bean 或枚舉實現。
ThreadPoolExecutor)、連接池(HikariCP)、對象池(Apache Commons Pool2)。// ✅ Java 7+ 標準寫法,異常也能自動關閉
try (Connection conn = ds.getConnection();
PreparedStatement ps = conn.prepareStatement(sql);
ResultSet rs = ps.executeQuery()) {
// 邏輯
}
舊代碼 finally { closeQuietly() } 全量替換。
-Xms -Xmx -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=.jstat -gcutil <pid> 1000、jconsole、VisualVM、Arthas(dashboard、heapdump)。MAT (Memory Analyzer Tool) 找 GC Roots、支配樹、洩漏疑點報告。-Xlog:gc*:file=gc.log:time,uptime,level,tags(JDK 9+),配合 GCViewer/GCEasy 分析。| # | 鐵律 | 關鍵動作 |
|---|---|---|
| 1 | 包裝類用工廠方法 | Integer.valueOf()、Boolean.valueOf() |
| 2 | 字符串拼接用 Builder | StringBuilder 替代 + |
| 3 | 緩存必有界限與淘汰 | Caffeine/Ehcache/Redis + 配置上限 |
| 4 | 扁平化類結構、縮短調用鏈 | 組合>繼承,熱點<10層 |
| 5 | 變量晚創建早釋放 | 縮小作用域,大對象置 null |
| 6 | 禁用 static 可變狀態 | 常量 final,狀態交給 Spring 管理 |
| 7 | 高頻對象用池化 | 線程/連接/對象池 |
| 8 | 資源 try-with-resources 關閉 | Connection/Stream/Socket 全覆蓋 |
| 9 | 建立監控分析體系 | JVM參數+GC日誌+堆轉儲+Arthas |
內存優化無銀彈,習慣決定質量。將這 9 條鐵律內化為團隊 Code Review 標準,配合持續監控,Java 應用照樣能跑得輕快穩健。