開發(fā)一個icp網(wǎng)站需要多少錢營銷型網(wǎng)站建設(shè)企業(yè)
常見OOM異常分析排查
- Java內(nèi)存溢出
- Java堆溢出原因
- 解決思路
- 總結(jié)
Java內(nèi)存溢出
java堆用于存儲對象實例,如果不斷地創(chuàng)建對象,并且保證GC Root到對象之間有可達(dá)路徑,垃圾回收機(jī)制就不會清理這些對象,對象數(shù)量達(dá)到最大堆的容量限制后就會產(chǎn)生內(nèi)存溢出異常.
Java堆溢出原因
- 無法在java堆中分配對象
- 應(yīng)用程序保存了無法被GC回收的對象
- 應(yīng)用程序過度使用finalizer
解決思路
- 查找關(guān)鍵報錯信息如
java.lang.StackOverflowError
java.lang.OutOfMemoryError:java heap space
java.lang.OutOfMemoryError:GC overhead limit exceeeded
java.lang.OutOfMemoryError:Direct buffer memory
java.lang.OutOfMemoryError:unable to create new native thread
java.lang.OutOfMemoryError:Metaspace
- 找到j(luò)ava進(jìn)程的ID(PID),使用 jps -vl 命令即可找到j(luò)ava進(jìn)程的PID和啟動時設(shè)置的jvm參數(shù)。
jps -vl
- 查看新生代,老年代堆內(nèi)存的分配大小以及使用情況
jmap -heap PID
[xxx@xxx ~]# jmap -heap 15162
Attaching to process ID 15162, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.161-b12using thread-local object allocation.
Mark Sweep Compact GCHeap Configuration:MinHeapFreeRatio = 40 # 最小堆使用比例MaxHeapFreeRatio = 70 # 最大堆可用比例MaxHeapSize = 482344960 (460.0MB) # 最大堆空間大小NewSize = 10485760 (10.0MB) # 新生代分配大小MaxNewSize = 160759808 (153.3125MB) # 最大新生代可分配大小OldSize = 20971520 (20.0MB) # 老年代大小NewRatio = 2 # 新生代比例SurvivorRatio = 8 # 新生代與 Survivor 比例MetaspaceSize = 21807104 (20.796875MB) # 元空間大小CompressedClassSpaceSize = 1073741824 (1024.0MB) # Compressed Class Space 空間大小限制MaxMetaspaceSize = 17592186044415 MB # 最大元空間大小G1HeapRegionSize = 0 (0.0MB) # G1 單個 Region 大小Heap Usage: # 堆使用情況
New Generation (Eden + 1 Survivor Space): # 新生代capacity = 9502720 (9.0625MB) # 新生代總?cè)萘?/span>used = 4995320 (4.763908386230469MB) # 新生代已使用free = 4507400 (4.298591613769531MB) # 新生代剩余容量52.56726495150862% used # 新生代使用占比
Eden Space: capacity = 8454144 (8.0625MB) # Eden 區(qū)總?cè)萘?/span>used = 4029752 (3.8430709838867188MB) # Eden 區(qū)已使用free = 4424392 (4.219429016113281MB) # Eden 區(qū)剩余容量47.665996699370154% used # Eden 區(qū)使用占比
From Space: # 其中一個 Survivor 區(qū)的內(nèi)存分布capacity = 1048576 (1.0MB)used = 965568 (0.92083740234375MB)free = 83008 (0.07916259765625MB)92.083740234375% used
To Space: # 另一個 Survivor 區(qū)的內(nèi)存分布capacity = 1048576 (1.0MB)used = 0 (0.0MB)free = 1048576 (1.0MB)0.0% used
tenured generation: # 老年代capacity = 20971520 (20.0MB)used = 10611384 (10.119804382324219MB)free = 10360136 (9.880195617675781MB)50.599021911621094% used10730 interned Strings occupying 906232 bytes.
- 查詢最耗內(nèi)存的對象,會以表格的形式顯示存活對象的信息,并按照所占內(nèi)存大小排序,信息有 排名,實例數(shù),所占內(nèi)存大小,類名
jmap -histo:live PID | more
- Dump文件分析
Dump 文件是 Java 進(jìn)程的內(nèi)存鏡像,其中主要包括 系統(tǒng)信息、虛擬機(jī)屬性、完整的線程 Dump、所有類和對象的狀態(tài) 等信息.
JVM 啟動參數(shù)配置添加以下參數(shù)
- -XX:+HeapDumpOnOutOfMemoryError
- -XX:HeapDumpPath=./(參數(shù)為 Dump 文件生成路徑)
JVM 啟動參數(shù)配置添加以下參數(shù)
上面配置是在應(yīng)用拋出 OOM 后自動導(dǎo)出 Dump,或者可以在 JVM 運行時導(dǎo)出 Dump 文件
jmap -dump:file=[文件路徑] [pid]# 示例
jmap -dump:file=./jvmdump.hprof 15892
Demo
設(shè)置 VM 參數(shù):-Xms3m -Xmx3m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=./public static void main(String[] args) {List<Object> oomList = Lists.newArrayList();// 無限循環(huán)創(chuàng)建對象while (true) {oomList.add(new Object());}
}
總結(jié)
線上如遇到 JVM 內(nèi)存溢出,可以分以下幾步排查
jmap -heap 查看是否內(nèi)存分配過小
jmap -histo 查看是否有明顯的對象分配過多且沒有釋放情況
jmap -dump 導(dǎo)出 JVM 當(dāng)前內(nèi)存快照,使用 JDK 自帶或 MAT 等工具分析快照