1. 內(nèi)存泄漏排查攻略之:Show me your Memory

        共 10098字,需瀏覽 21分鐘

         ·

        2021-06-15 21:17


        來源| cnblogs.com/yougewe/p/11334342.html


        java 語言有個(gè)神奇的地方,那就是你時(shí)不時(shí)會(huì)去關(guān)注下內(nèi)存。(當(dāng)然了,任何牛逼的同學(xué)都應(yīng)該關(guān)注內(nèi)存)

        今天我們就來這么個(gè)問題現(xiàn)場(chǎng)吧:某應(yīng)用運(yùn)行了一段時(shí)間后,ecs監(jiān)控報(bào)警了,內(nèi)存比較高了,怎么辦?隨著時(shí)間的推移,發(fā)現(xiàn)內(nèi)存越來越高緩緩增長(zhǎng),怎么辦?

        凡事講究證據(jù),報(bào)警系統(tǒng)說內(nèi)存緊張就緊張嗎,還得自己去驗(yàn)一下。

        如何確認(rèn)內(nèi)存問題?這太重要了!其實(shí)只要給我看你內(nèi)存里所有東西(Show me your Memory),我豈有找不到問題根源的道理?以下是幾種查看內(nèi)存問題的方法供諸君參考:

        1:top 等查看系統(tǒng)內(nèi)存概況

        top:顯示所有進(jìn)程運(yùn)行情況,按M鍵按照內(nèi)存大小排序,立馬看到罪魁禍?zhǔn)?。具體命令請(qǐng)參考網(wǎng)上資料。

        top簡(jiǎn)要使用方法如下:

        使用格式:top [-] [d] [p] [q] [c] [C] [S] [s] [n]參數(shù)說明:d:指定每?jī)纱纹聊恍畔⑺⑿轮g的時(shí)間間隔。當(dāng)然用戶可以使用s交互命令來改變之。p:通過指定監(jiān)控進(jìn)程ID來僅僅監(jiān)控某個(gè)進(jìn)程的狀態(tài)。q:該選項(xiàng)將使top沒有任何延遲的進(jìn)行刷新。如果調(diào)用程序有超級(jí)用戶權(quán)限,那么top將以盡可能高的優(yōu)先級(jí)運(yùn)行。S:指定累計(jì)模式。s:使top命令在安全模式中運(yùn)行。這將去除交互命令所帶來的潛在危險(xiǎn)。i:使top不顯示任何閑置或者僵死進(jìn)程。c:顯示整個(gè)命令行而不只是顯示命令名。
        常用命令說明:Ctrl+L:擦除并且重寫屏幕K:終止一個(gè)進(jìn)程。系統(tǒng)將提示用戶輸入需要終止的進(jìn)程PID,以及需要發(fā)送給該進(jìn)程什么樣的信號(hào)。一般的終止進(jìn)程可以使用15信號(hào);如果不能正常結(jié)束那就使用信號(hào)9強(qiáng)制結(jié)束該進(jìn)程。默認(rèn)值是信號(hào)15。在安全模式中此命令被屏蔽。i:忽略閑置和僵死進(jìn)程。這是一個(gè)開關(guān)式命令。q:退出程序r:重新安排一個(gè)進(jìn)程的優(yōu)先級(jí)別。系統(tǒng)提示用戶輸入需要改變的進(jìn)程PID以及需要設(shè)置的進(jìn)程優(yōu)先級(jí)值。輸入一個(gè)正值將使優(yōu)先級(jí)降低,反之則可以使該進(jìn)程擁有更高的優(yōu)先權(quán)。默認(rèn)值是10。S:切換到累計(jì)模式。s:改變兩次刷新之間的延遲時(shí)間。系統(tǒng)將提示用戶輸入新的時(shí)間,單位為s。如果有小數(shù),就換算成m s。輸入0值則系統(tǒng)將不斷刷新,默認(rèn)值是5 s。需要注意的是如果設(shè)置太小的時(shí)間,很可能會(huì)引起不斷刷新,從而根本來不及看清顯示的情況,而且系統(tǒng)負(fù)載也會(huì)大大增加。f或者F:從當(dāng)前顯示中添加或者刪除項(xiàng)目。o或者O:改變顯示項(xiàng)目的順序l:切換顯示平均負(fù)載和啟動(dòng)時(shí)間信息。m:切換顯示內(nèi)存信息。t:切換顯示進(jìn)程和CPU狀態(tài)信息。c:切換顯示命令名稱和完整命令行。M:根據(jù)駐留內(nèi)存大小進(jìn)行排序。P:根據(jù)CPU使用百分比大小進(jìn)行排序。T:根據(jù)時(shí)間/累計(jì)時(shí)間進(jìn)行排序。W:將當(dāng)前設(shè)置寫入~/.toprc文件中。

        另外在內(nèi)存查看方面,還可以使用 free用于快速直接查看內(nèi)存,還可以看到有多少是系統(tǒng)緩存;(系統(tǒng)緩存一般不被計(jì)入真正已使用內(nèi)存中)

        2. jmx 快速發(fā)現(xiàn)jvm中的內(nèi)存異常項(xiàng)

        jmx,如果開啟了jmx,則我們可以直接通過jvisualvm查看內(nèi)存,線程監(jiān)控情況,還可以查看其他jmx指標(biāo);
        從這里你可以,看到內(nèi)存的變化趨勢(shì),垃圾回收,cpu變化趨勢(shì)等等,很多直觀的問題完全可以在這一環(huán)節(jié)發(fā)現(xiàn)。
        另外,你可以通過采集cpu和采集內(nèi)存的方式,發(fā)現(xiàn)代碼中的瓶頸點(diǎn)。
        可以說,jmx是我們進(jìn)行代碼優(yōu)化或者參數(shù)調(diào)優(yōu)的絕對(duì)王者工具。

        性能問題,可以適當(dāng)進(jìn)行CPU/內(nèi)存采樣,以快速發(fā)現(xiàn)瓶頸點(diǎn)!

        建議新增插件: 

        Btrace Workbench  用于遠(yuǎn)程調(diào)試,也許有用;

        BufferMonitor 用于查看堆外內(nèi)存情況,其實(shí)可能不準(zhǔn);

        Threads Inspector 用于快速查看各線程情況;

        VisualJVM-MBeans 用于查看 jmx 暴露出來的 指標(biāo)信息,可作為業(yè)務(wù)監(jiān)控使用;

        3. jmap dump 詳細(xì)分析jvm的內(nèi)存使用情況

        jmap dump,發(fā)現(xiàn)內(nèi)存異常,而其他方面沒啥思路時(shí),那就jvm內(nèi)存dump下來,慢慢分析。
        dump整個(gè)內(nèi)存下來,全量分析,jmap -dump:format=b,file=/tmp/a.dump . 然后就可以使用jvm內(nèi)存分析工具進(jìn)行分析了,如 mat 。分析工具的技巧可能還是需要去掌握下的,不過我這里簡(jiǎn)單提兩個(gè)點(diǎn),一個(gè)是看得到的堆內(nèi)存,一個(gè)是不可達(dá)的堆內(nèi)存,分析時(shí)就注意這兩點(diǎn)。一般可達(dá)堆內(nèi)存是很好分析的,不可達(dá)堆內(nèi)存則要憑借一定的經(jīng)驗(yàn)才能發(fā)現(xiàn)問題了。

        對(duì)于快速查詢,則直接在服務(wù)器上使用 jmap -heap 就可以查看了。

        jmap -dump:format=b,file=/tmp/a.dump <pid> # dump倒是堆內(nèi)存jmap -heap <pid> # 直接在服務(wù)器上查看堆的使用情況

        會(huì)一些OQL查詢語言,將會(huì)對(duì)你的排查如虎添翼! 

        4. lsof 列舉出正在使用的文件,看看是否能發(fā)現(xiàn)一些端倪

        lsof,這個(gè)工具用于排查是否存在很在很多超出預(yù)料的文件的情況,比如打開某文件未關(guān)閉,建立很多的socket連接等等。當(dāng)然,發(fā)現(xiàn)問題只能靠眼力勁了。

        lsof -p <pid> #查看進(jìn)程打開的文件情況。

        lsof 使用詳細(xì)介紹參考網(wǎng)上資料: https://www.cnblogs.com/sparkbj/p/7161669.html

        5. pmap 查看進(jìn)程內(nèi)存概要

        pmap,用于查看進(jìn)程的內(nèi)存映像信息, 發(fā)現(xiàn)內(nèi)存中大塊的占用所在,以及分析內(nèi)存可能存在的異常。

        從中,你可以看到哪些內(nèi)存上面占用了多少內(nèi)存,正常的內(nèi)存如 JVM 所在內(nèi)存段,應(yīng)該是和你的堆內(nèi)存一致的,而其他內(nèi)存段,則是你看不到的地方,這些地方將是你排查內(nèi)存泄漏的方向。

        簡(jiǎn)要命令下:    pmap [ -x | -d ] [ -q ] pids...結(jié)果樣例如下:[root@abtest ~]# pmap -x 27466 27466:   /usr/local/jdk1.8.0_211/bin/java -Dzookeeper.log.dir=. -Dzookeeper.root.logger=INFO,CONSOLE -cp /opt/zookeeper/zookeeper-3.4.14/bin/../zookeeper-server/target/classes:/opt/zookeeper/zookeeper-3.4.14/bin/../build/classes:/opt/zookeeper/zookeeper-3.4.14/bin/../zookeeper-server/target/lib/*.jar:/opt/zookeeper/zookeeper-3.4.14/bin/../build/lib/*.jar:/opt/zookeeper/zookeeper-3.4.14/bin/../lib/slf4j-log4j12-1.7.25.jar:/opt/zookeeper/zookeeper-3.4.14/bin/../lib/slf4j-api-1.7.25.jar:/opt/zookeeper/zookeeper-3.4.1Address           Kbytes     RSS   Dirty Mode  Mapping0000000000400000       4       4       0 r-x-- java0000000000600000       4       4       4 r---- java0000000000601000       4       4       4 rw--- java...00007fff10253000     136      36      36 rw---   [ stack ]00007fff102ce000       8       4       0 r-x--   [ anon ]ffffffffff600000       4       0       0 r-x--   [ anon ]---------------- ------- ------- -------total kB         5421732  100608   87672

        命令操作詳情請(qǐng)參考網(wǎng)上資料:: https://www.cnblogs.com/txw1958/archive/2012/07/26/linux-pmap.html


        6. NMT,  nativeMemoryTracking jvm 的內(nèi)存追蹤工具

        nmt,這個(gè)jdk8以后,jvm提供的內(nèi)存跟蹤工具,nativeMemoryTracking, 可以用于排查內(nèi)存方案的問題。 

        -XX:NativeMemoryTracking=summary     # 開啟NMT追蹤jcmd 1 VM.native_memory summary        # 查看當(dāng)前的內(nèi)存概況jcmd 1 VM.native_memory baseline    # 創(chuàng)建基準(zhǔn) baselinejcmd 1 VM.native_memory summary.diff    # 一段時(shí)間后,比對(duì)內(nèi)存差異,可以用于發(fā)現(xiàn)內(nèi)存的走向問題,如下[root@abtest ~]# jcmd 5545 VM.native_memory summary.diff5545:
        Native Memory Tracking:
        Total: reserved=5942859KB +2339KB, committed=4104347KB +1519KB
        - Java Heap (reserved=4194304KB, committed=3645440KB) (mmap: reserved=4194304KB, committed=3645440KB)
        - Class (reserved=1109328KB +2056KB, committed=66640KB +264KB) (classes #11172 +2) (malloc=1360KB +8KB #15153 +331) (mmap: reserved=1107968KB +2048KB, committed=65280KB +256KB)
        - Thread (reserved=133119KB, committed=133119KB) (thread #130) (stack: reserved=132544KB, committed=132544KB) (malloc=422KB #652) (arena=152KB #256)
        - Code (reserved=255919KB +247KB, committed=37519KB +1219KB) (malloc=6319KB +247KB #8248 +270) (mmap: reserved=249600KB, committed=31200KB +972KB)
        - GC (reserved=209075KB +8KB, committed=188707KB +8KB) (malloc=20659KB +8KB #28406 +320) (mmap: reserved=188416KB, committed=168048KB)
        - Compiler (reserved=277KB +5KB, committed=277KB +5KB) (malloc=146KB +5KB #592 +9) (arena=131KB #6)
        - Internal (reserved=12648KB, committed=12648KB) (malloc=12616KB #39090 +5) (mmap: reserved=32KB, committed=32KB)
        - Symbol (reserved=16444KB +8KB, committed=16444KB +8KB) (malloc=12569KB +8KB #121265 +2) (arena=3876KB #1)
        - Native Memory Tracking (reserved=3362KB +15KB, committed=3362KB +15KB) (malloc=18KB #204 +2) (tracking overhead=3344KB +15KB)
        - Arena Chunk (reserved=192KB, committed=192KB) (malloc=192KB)
        - Unknown (reserved=8192KB, committed=0KB) (mmap: reserved=8192KB, committed=0KB)

        如上結(jié)果,我們可以得得出些結(jié)論,隨著時(shí)間的推移, code 部分的占用空間增加了最多(JIT), Compiler 也增加一些,而堆內(nèi)存則一直保持不變!

        7. perf,這是一個(gè)性能監(jiān)控調(diào)優(yōu)工具,但是我們也可能從中發(fā)現(xiàn)內(nèi)存問題點(diǎn)

        可以先捕獲數(shù)據(jù),然后進(jìn)行性能分析,然后得到可疑的點(diǎn)。

        幫助信息如下:

        usage: perf [--version] [--help] [OPTIONS] COMMAND [ARGS] The most commonly used perf commands are:   annotate        Read perf.data (created by perf record) and display annotated code   archive         Create archive with object files with build-ids found in perf.data file   bench           General framework for benchmark suites   buildid-cache   Manage build-id cache.   buildid-list    List the buildids in a perf.data file   c2c             Shared Data C2C/HITM Analyzer.   config          Get and set variables in a configuration file.   data            Data file related processing   diff            Read perf.data files and display the differential profile   evlist          List the event names in a perf.data file   ftrace          simple wrapper for kernel's ftrace functionality   inject          Filter to augment the events stream with additional information   kallsyms        Searches running kernel for symbols   kmem            Tool to trace/measure kernel memory properties   kvm             Tool to trace/measure kvm guest os   list            List all symbolic event types   lock            Analyze lock events   mem             Profile memory accesses   record          Run a command and record its profile into perf.data   report          Read perf.data (created by perf record) and display the profile   sched           Tool to trace/measure scheduler properties (latencies)   script          Read perf.data (created by perf record) and display trace output   stat            Run a command and gather performance counter statistics   test            Runs sanity tests.   timechart       Tool to visualize total system behavior during a workload   top             System profiling tool.   probe           Define new dynamic tracepoints   trace           strace inspired tool
        See 'perf help COMMAND' for more information on a specific command.

        簡(jiǎn)單示例:

            perf record -g -e cpu-clock -p 5545        # 記錄進(jìn)程 5545 的相關(guān)性能信息    perf report -i perf.data                # 讀取剛剛記錄的數(shù)據(jù),可以顯示出種操作的占用情況,如下Samples: 908  of event 'cpu-clock', Event count (approx.): 227000000  Children      Self  Command  Shared Object       Symbol+   32.27%     0.00%  java     libpthread-2.17.so  [.] start_thread+   32.27%     0.00%  java     libjvm.so           [.] java_start+   26.54%     0.00%  java     libjvm.so           [.] ConcurrentG1RefineThread::run+   26.54%     0.11%  java     libjvm.so           [.] ConcurrentG1RefineThread::run_young_rs_sampling+   25.77%     5.62%  java     libjvm.so           [.] YoungList::rs_length_sampling_next+   22.58%     0.55%  java     [kernel.kallsyms]   [k] tracesys+   11.01%     0.00%  java     perf-5545.map       [.] 0x00007f553ec1e981+   10.79%     0.44%  java     libjvm.so           [.] JVM_Sleep+    9.36%     0.55%  java     libjvm.so           [.] G1CollectorPolicy::update_incremental_cset_info+    8.70%     0.55%  java     libjvm.so           [.] os::sleep+    8.26%     0.00%  java     [unknown]           [k] 0xee83b0ac00709650+    8.15%     0.99%  java     libpthread-2.17.so  [.] pthread_cond_timedwait@@GLIBC_2.3.2+    7.93%     0.00%  java     perf-5545.map       [.] 0x00007f553f7f7d30

        如果運(yùn)氣碰巧的話,你有可能能查到某些異常的操作,從而推斷出問題所在。

        8. gdb 調(diào)試工具dump出可疑內(nèi)存

        gdb, linux下強(qiáng)大的調(diào)試工具,但是我們不用它來調(diào)試,我們只用來輸出內(nèi)存的內(nèi)容。即dump內(nèi)存,前面用到的jmap dump只能看到j(luò)vm的內(nèi)存信息,而gdb則可以看所有的,當(dāng)然我們會(huì)用來看其他部分的內(nèi)存。

            gdb attach <pid>                    # 先連接到進(jìn)程中    gdb dump memory /path/dump.bin 0x0011  0x0021    # dump 出內(nèi)存段的信息,具體要 dump 的內(nèi)存段地址,可以借助之前pmap 排查的結(jié)果,以及 cat /proc/<pid>/maps 中指示的地址段得出    strings /path/dump.bin | less # 查看內(nèi)存內(nèi)容, 相信你能從中發(fā)現(xiàn)一些不一樣的東西

        以上,足夠你排查出你懷疑的內(nèi)存泄露問題了。如果不能,說明你還用好工具,多練練!

        END


        推薦閱讀:

        世界的真實(shí)格局分析,地球人類社會(huì)底層運(yùn)行原理

        企業(yè)IT技術(shù)架構(gòu)規(guī)劃方案

        論數(shù)字化轉(zhuǎn)型——轉(zhuǎn)什么,如何轉(zhuǎn)?

        企業(yè)10大管理流程圖,數(shù)字化轉(zhuǎn)型從業(yè)者必備!

        【中臺(tái)實(shí)踐】華為大數(shù)據(jù)中臺(tái)架構(gòu)分享.pdf

        華為的數(shù)字化轉(zhuǎn)型方法論

        華為如何實(shí)施數(shù)字化轉(zhuǎn)型(附PPT)

        超詳細(xì)280頁Docker實(shí)戰(zhàn)文檔!開放下載

        華為大數(shù)據(jù)解決方案(PPT)


        瀏覽 65
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        評(píng)論
        圖片
        表情
        推薦
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
          
          

            1. 老女人操逼视频网站 | www.草草草草草草 | 欧美性爱在线网站 | 玖玖成人免费视频 | 色婷婷亚洲综合网 |