成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

教你如何成為Java的OOM Killer

開發 開發工具
雖然事隔半年,當時排查線上OOM事故的過程記憶猶新,每一個步驟都歷歷在目,感謝業務組、系統部、壓測組、監控與應急部對架構組的強力支持,得以讓這個Java內存問題水落石出,經過半年多的全面的應用日志切割方式的改造,現在基本沒有OOM的問題了,線上服務運行非常健康,對可用性的保障起到了很大的作用,如果你在經歷OOM,讀了這個文章會有很大的啟發。

[[196172]]

前言

雖然事隔半年,當時排查線上OOM事故的過程記憶猶新,每一個步驟都歷歷在目,感謝業務組、系統部、壓測組、監控與應急部對架構組的強力支持,得以讓這個Java內存問題水落石出,經過半年多的全面的應用日志切割方式的改造,現在基本沒有OOM的問題了,線上服務運行非常健康,對可用性的保障起到了很大的作用,如果你在經歷OOM,讀了這個文章會有很大的啟發。

Become OOM Killer

我們都知道JVM的內存管理是自動化的,Java語言的程序指針也不需要開發人員手工釋放,JVM的GC會自動的進行回收,但是,如果編程不當,JVM仍然會發生內存泄露,導致Java程序產生了OutOfMemoryError(OOM)錯誤。

產生OutOfMemoryError錯誤的原因包括:

  1. java.lang.OutOfMemoryError: Java heap space
  2. java.lang.OutOfMemoryError: PermGen space及其解決方法
  3. java.lang.OutOfMemoryError: unable to create new native thread
  4. java.lang.OutOfMemoryError:GC overhead limit exceeded

對于第1種異常,表示Java堆空間不夠,當應用程序申請更多的內存,而Java堆內存已經無法滿足應用程序對內存的需要,將拋出這種異常。

對于第2種異常,表示Java永久帶(方法區)空間不夠,永久帶用于存放類的字節碼和長常量池,類的字節碼加載后存放在這個區域,這和存放對象實例的堆區是不同的,大多數JVM的實現都不會對永久帶進行垃圾回收,因此,只要類加載的過多就會出現這個問題。一般的應用程序都不會產生這個錯誤,然而,對于Web服務器來講,會產生有大量的JSP,JSP在運行時被動態的編譯成Java Servlet類,然后加載到方法區,因此,太多的JSP的Web工程可能產生這個異常。

對于第3種異常,本質原因是創建了太多的線程,而能創建的線程數是有限制的,導致了這種異常的發生。

對于第4種異常,是在并行或者并發回收器在GC回收時間過長、超過98%的時間用來做GC并且回收了不到2%的堆內存,然后拋出這種異常進行提前預警,用來避免內存過小造成應用不能正常工作。

下面兩個異常與OOM有關系,但是,又沒有絕對關系。

  1. java.lang.StackOverflowError ...
  2. java.net.SocketException: Too many open files

對于第1種異常,是JVM的線程由于遞歸或者方法調用層次太多,占滿了線程堆棧而導致的,線程堆棧默認大小為1M。

對于第2種異常,是由于系統對文件句柄的使用是有限制的,而某個應用程序使用的文件句柄超過了這個限制,就會導致這個問題。

上面介紹了OOM相關的基礎知識,接下來我們開始講述筆者經歷的一次OOM問題的定位和解決的過程。

1. 產生問題的現象

在某一段時間內,我們發現不同的業務服務開始偶發的報OOM的異常,有的時候是白天發生,有的時候是晚上發生,有的時候是基礎服務A發生,有的時候是上層服務B發生,有的時候是上層服務C發生,有的時候是下層服務D發生,絲毫看不到一點規律。

產生問題的異常如下:

  1. Caused by: java.lang.OutOfMemoryError: unable to create new native thread at java.lang.Thread.start0(Native Method) 
  2. at java.lang.Thread.start(Thread.java:597) 
  3. at java.util.Timer.<init>(Timer.java:154) 

2. 解決問題的思路和過程

經過細心觀察發現,產生問題雖然在不同的時間發生在不同的服務池,但是,晚上0點發生的時候概率較大,也有其他時間偶發,但是都在整點。

這個規律很重要,雖然不是一個時間,但是基本都在整點左右發生,并且晚上0點居多。從這個角度思考,整點或者0點系統是否有定時,與出問題的每個業務系統技術負責人核實,0點沒有定時任務,其他時間的整點有定時任務,但是與發生問題的時間不吻合,這個思路行不通。

到現在為止,從現象的規律上我們已經沒法繼續分析下去了,那我們回顧一下錯誤本身:

  1. java.lang.OutOfMemoryError: unable to create new native thread

顧名思義,錯誤產生的原因就是應用不能創建線程了,但是,應用還需要創建線程。為什么程序不能創建線程呢?

有兩個具體原因造成這個異常:

  1. 由于線程使用的資源過多,操作系統已經不能再提供給應用資源了。
  2. 操作系統設置了應用創建線程的最大數量,并且已經達到了最大允許數量。

上面第1條資源指的是內存,而第2條中,在Linux下線程使用輕量級進程實現的,因此線程的最大數量也是操作系統允許的進程的最大數量。

內存計算

操作系統中的最大可用內存除去操作系統本身使用的部分,剩下的都可以為某一個進程服務,在JVM進程中,內存又被分為堆、本地內存和棧等三大塊,Java堆是JVM自動管理的內存,應用的對象的創建和銷毀、類的裝載等都發生在這里,本地內存是Java應用使用的一種特殊內存,JVM并不直接管理其生命周期,每個線程也會有一個棧,是用來存儲線程工作過程中產生的方法局部變量、方法參數和返回值的,每個線程對應的棧的默認大小為1M。

Linux和JVM的內存管理示意圖如下:

內存結構模型

因此,從內存角度來看創建線程需要內存空間,如果JVM進程正當一個應用創建線程,而操作系統沒有剩余的內存分配給此JVM進程,則會拋出問題中的OOM異常:unable to create new native thread。

如下公式可以用來從內存角度計算允許創建的最大線程數:

  • 最大線程數 = (操作系統最大可用內存 - JVM內存 - 操作系統預留內存)/ 線程棧大小

根據這個公式,我們可以通過剩余內存計算可以創建線程的數量。

下面是問題出現的時候,從生產機器上執行前面小節介紹的Linux命令free的輸出:

  1. free -m >> /tmp/free.log 
  2.              total       used       free     shared    buffers     cached 
  3. Mem:          7872       7163        709          0         31       3807 
  4. -/+ buffers/cache:       3324       4547 
  5. Swap:         4095        173       3922 
  6. Tue Jul 5 00:27:51 CST 2016 

從上面輸出可以得出,生產機器8G內存,使用了7G,剩余700M可用,其中操作系統cache使用3.8G。操作系統cache使用的3.8G是用來緩存IO數據的,如果進程內存不夠用,這些內存是可以釋放出來優先分配給進程使用。然而,我們暫時并不需要考慮這塊內存,剩余的700M空間完全可以繼續用來創建線程數:

  • 700M / 1M = 700個線程

因此,根據內存可用計算,當OOM異常:unable to create new native thread問題發生的時候,還有700M可用內存,可以創建700個線程。

到現在為止可以證明此次OOM異常不是因為線程吃光所有的內存而導致的。

線程數對比

上面提到,有兩個具體原因造成這個異常,我們上面已經排除了第1個原因,那我們現在從第2個原因入手,評估是否操作系統設置了應用創建線程的最大數量,并且已經達到了最大允許數量。

在問題出現的生產機器上使用ulimit -a來顯示當前的各種系統對用戶使用資源的限制:

  1. robert@robert-ubuntu1410:~$ ulimit -a 
  2. core file size          (blocks, -c) 0 
  3. data seg size           (kbytes, -d) unlimited 
  4. scheduling priority             (-e) 0 
  5. file size               (blocks, -f) unlimited 
  6. pending signals                 (-i) 62819 
  7. max locked memory       (kbytes, -l) 64 
  8. max memory size         (kbytes, -m) unlimited 
  9. open files                      (-n) 65535 
  10. pipe size            (512 bytes, -p) 8 
  11. POSIX message queues     (bytes, -q) 819200 
  12. real-time priority              (-r) 0 
  13. stack size              (kbytes, -s) 10240 
  14. cpu time               (seconds, -t) unlimited 
  15. max user processes              (-u) 1024 
  16. virtual memory          (kbytes, -v) unlimited 
  17. file locks                      (-x) unlimited 

這里面我們看到生產機器設置的允許使用的最大用戶進程數為1024:

  1. max user processes (-u) 1024 

現在,我們必須獲得問題出現的時候,用戶下創建的線程情況。

在問題產生的時候,我們使用前面小結介紹的JVM監控命令jstack命令打印出了Java線程情況,jstack命令的示例輸出如下:

  1. robert@robert-ubuntu1410:~$ jstack 2743 
  2. 2017-04-09 12:06:51 
  3. Full thread dump Java HotSpot(TM) Server VM (25.20-b23 mixed mode): 
  4.  
  5. "Attach Listener" #23 daemon prio=9 os_prio=0 tid=0xc09adc00 nid=0xb4c waiting on condition [0x00000000] 
  6.    java.lang.Thread.State: RUNNABLE 
  7.  
  8. "http-nio-8080-Acceptor-0" #22 daemon prio=5 os_prio=0 tid=0xc3341000 nid=0xb02 runnable [0xbf1bd000] 
  9.    java.lang.Thread.State: RUNNABLE 
  10.     at sun.nio.ch.ServerSocketChannelImpl.accept0(Native Method) 
  11.     at sun.nio.ch.ServerSocketChannelImpl.accept(ServerSocketChannelImpl.java:241) 
  12.     - locked <0xcf8938d8> (a java.lang.Object) 
  13.     at org.apache.tomcat.util.net.NioEndpoint$Acceptor.run(NioEndpoint.java:688) 
  14.     at java.lang.Thread.run(Thread.java:745) 
  15.  
  16. "http-nio-8080-ClientPoller-1" #21 daemon prio=5 os_prio=0 tid=0xc35bc400 nid=0xb01 runnable [0xbf1fe000] 
  17.    java.lang.Thread.State: RUNNABLE 
  18.     at sun.nio.ch.EPollArrayWrapper.epollWait(Native Method) 
  19.     at sun.nio.ch.EPollArrayWrapper.poll(EPollArrayWrapper.java:269) 
  20.     at sun.nio.ch.EPollSelectorImpl.doSelect(EPollSelectorImpl.java:79) 
  21.     at sun.nio.ch.SelectorImpl.lockAndDoSelect(SelectorImpl.java:86) 
  22.     - locked <0xcf99b100> (a sun.nio.ch.Util$2) 
  23.     - locked <0xcf99b0f0> (a java.util.Collections$UnmodifiableSet) 
  24.     - locked <0xcf99aff8> (a sun.nio.ch.EPollSelectorImpl) 
  25.     at sun.nio.ch.SelectorImpl.select(SelectorImpl.java:97) 
  26.     at org.apache.tomcat.util.net.NioEndpoint$Poller.run(NioEndpoint.java:1052) 
  27.     at java.lang.Thread.run(Thread.java:745) 
  28. ...... 

從jstack命令的輸出并統計后,我們得知,JVM一共創建了904個線程,但是,這還沒有到最大的進程限制1024。

  1. robert@robert-ubuntu1410:~$ grep "Thread " js.log | wc -l 
  2.      904 

這是我們思考,除了JVM創建的應用層線程,JVM本身可能會有一些管理線程存在,而且操作系統內用戶下可能也會有守護線程在運行。

我們繼續從操作系統的角度來統計線程數,我們使用上面小結介紹的Linux操作系統命令pstack,并得到如下的輸出:

  1. PID   LWP USER     %CPU %MEM CMD 
  2.     1     1 root      0.0  0.0 /sbin/init 
  3.     2     2 root      0.0  0.0 [kthreadd] 
  4.     3     3 root      0.0  0.0 [migration/0] 
  5.     4     4 root      0.0  0.0 [ksoftirqd/0] 
  6.     5     5 root      0.0  0.0 [migration/0] 
  7.     6     6 root      0.0  0.0 [watchdog/0] 
  8.     7     7 root      0.0  0.0 [migration/1] 
  9.     8     8 root      0.0  0.0 [migration/1] 
  10.     9     9 root      0.0  0.0 [ksoftirqd/1] 
  11.    10    10 root      0.0  0.0 [watchdog/1] 
  12.    11    11 root      0.0  0.0 [migration/2] 
  13.    12    12 root      0.0  0.0 [migration/2] 
  14.    13    13 root      0.0  0.0 [ksoftirqd/2] 
  15.    14    14 root      0.0  0.0 [watchdog/2] 
  16.    15    15 root      0.0  0.0 [migration/3] 
  17.    16    16 root      0.0  0.0 [migration/3] 
  18.    17    17 root      0.0  0.0 [ksoftirqd/3] 
  19.    18    18 root      0.0  0.0 [watchdog/3] 
  20.    19    19 root      0.0  0.0 [events/0] 
  21.    20    20 root      0.0  0.0 [events/1] 
  22.    21    21 root      0.0  0.0 [events/2] 
  23.    22    22 root      0.0  0.0 [events/3] 
  24.    23    23 root      0.0  0.0 [cgroup] 
  25.    24    24 root      0.0  0.0 [khelper] 
  26.  
  27.  ...... 
  28.  
  29.  7257  7257 zabbix    0.0  0.0 /usr/local/zabbix/sbin/zabbix_agentd: active checks #2 [idle 1 sec] 
  30.  7258  7258 zabbix    0.0  0.0 /usr/local/zabbix/sbin/zabbix_agentd: active checks #3 [idle 1 sec] 
  31.  7259  7259 zabbix    0.0  0.0 /usr/local/zabbix/sbin/zabbix_agentd: active checks #4 [idle 1 sec] 
  32.  
  33.  ...... 
  34.  
  35.  9040  9040 app       0.0 30.5 /apps/prod/jdk1.6.0_24/bin/java -Dnop -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Ddbconfigpath=/apps/dbconfig/ -Djava.io.tmpdir=/apps/data/java-tmpdir -server -Xms2048m -Xmx2048m -XX:PermSize=128m -XX:MaxPermSize=512m -Dcom.sun.management.jmxremote -Djava.rmi.server.hostname=192.168.10.194 -Dcom.sun.management.jmxremote.port=6969 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/tmp -Xshare:off -Dhostname=sjsa-trade04 -Djute.maxbuffer=41943040 -Djava.net.preferIPv4Stack=true -Dfile.encoding=UTF-8 -Dworkdir=/apps/data/tomcat-work -Djava.endorsed.dirs=/apps/product/tomcat-trade/endorsed -classpath commonlib:/apps/product/tomcat-trade/bin/bootstrap.jar:/apps/product/tomcat-trade/bin/tomcat-juli.jar -Dcatalina.base=/apps/product/tomcat-trade -Dcatalina.home=/apps/product/tomcat-trade -Djava.io.tmpdir=/apps/data/tomcat-temp/ org.apache.catalina.startup.Bootstrap start 
  36.  9040  9041 app       0.0 30.5 /apps/prod/jdk1.6.0_24/bin/java -Dnop -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Ddbconfigpath=/apps/dbconfig/ -Djava.io.tmpdir=/apps/data/java-tmpdir -server -Xms2048m -Xmx2048m -XX:PermSize=128m -XX:MaxPermSize=512m -Dcom.sun.management.jmxremote -Djava.rmi.server.hostname=192.168.10.194 -Dcom.sun.management.jmxremote.port=6969 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/tmp -Xshare:off -Dhostname=sjsa-trade04 -Djute.maxbuffer=41943040 -Djava.net.preferIPv4Stack=true -Dfile.encoding=UTF-8 -Dworkdir=/apps/data/tomcat-work -Djava.endorsed.dirs=/apps/product/tomcat-trade/endorsed -classpath commonlib:/apps/product/tomcat-trade/bin/bootstrap.jar:/apps/product/tomcat-trade/bin/tomcat-juli.jar -Dcatalina.base=/apps/product/tomcat-trade -Dcatalina.home=/apps/product/tomcat-trade -Djava.io.tmpdir=/apps/data/tomcat-temp/ org.apache.catalina.startup.Bootstrap start 
  37.  
  38. ...... 

通過命令統計用戶下已經創建的線程數為1021。

  1. $ grep app pthreads.log | wc -l 
  2.     1021 

現在我們確定,1021的數字已經相當的接近1021的最大進程數了,正如前面我們提到,在Linux操作系統里,線程是通過輕量級的進程實現的,因此,限制用戶的最大進程數,就是限制用戶的最大線程數,至于為什么沒有精確達到1024這個最大值就已經報出異常,應該是系統的自我保護功能,在還剩下3個線程的前提下,就開始報錯。

到此為止,我們已經通過分析來找到問題的原因,但是,我們還是不知道為什么會創建這么多的線程,從第一個輸出得知,JVM已經創建的應用線程有907個,那么他們都在做什么事情呢?

于是,在問題發生的時候,我們又使用JVM的jstack命令,查看輸出得知,每個線程都阻塞在打印日志的語句上,log4j中打印日志的代碼實現如下:

  1. public void callAppenders(LoggingEvent event) { 
  2.     int writes = 0; 
  3.     for(Category c = this; c != null; c=c.parent) { 
  4.         // Protected against simultaneous call to addAppender, removeAppender,... 
  5.         synchronized(c) { 
  6.             if(c.aai != null) { 
  7.                 writes += c.aai.appendLoopOnAppenders(event); 
  8.             } 
  9.             if(!c.additive) { 
  10.                 break; 
  11.             } 
  12.         } 
  13.     } 
  14.     if(writes == 0) { 
  15.         repository.emitNoAppenderWarning(this); 
  16.     } 

在log4j中,打印日志有一個鎖,鎖的作用是讓打印日志可以串行,保證日志在日志文件中的正確性和順序性。

那么,新的問題又來了,為什么只有凌晨0點會出現打印日志阻塞,其他時間會偶爾發生呢?這時,我們帶著新的線索又回到問題開始的思路,凌晨12點應用沒有定時任務,系統會不會有其他的IO密集型的任務,比如說歸檔日志、磁盤備份等?

經過與運維部門碰頭,基本確定是每天凌晨0點日志切割導致磁盤IO被占用,于是堵塞打印日志,日志是每個工作任務都必須的,日志阻塞,線程池就阻塞,線程池阻塞就導致線程池被撐大,線程池里面的線程數超過1024就會報錯。

到這里,我們基本確定了問題的原因,但是還需要對日志切割導致IO增大進行分析和論證。

首先我們使用前面小結介紹的vmstat查看問題發生時IO等待數據:

  1. vmstat 2 1 >> /tmp/vm.log 
  2. procs -----------memory---------- ---swap-- -----io---- --system-- -----cpu----- 
  3.  r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st 
  4.  3  0 177608 725636  31856 3899144    0    0     2    10    0    0  39  1 1  59  0     
  5. Tue Jul 5 00:27:51 CST 2016 

可見,問題發生的時候,CPU的IO等待為59%,同時又與運維部門同事復盤,運維同事確認,腳本切割通過cat命令方法,先把日志文件cat后,通過管道打印到另外一個文件,再清空原文件,因此,一定會導致IO的上升。

其實,問題的過程中,還有一個疑惑,我們認為線程被IO阻塞,線程池被撐開,導致線程增多,于是,我們查看了一下Tomcat線程池的設置,我們發現Tomcat線程池設置了800,按理說,永遠不會超過1024。

  1. <Connector port="8080"      
  2.                maxThreads="800" minSpareThreads="25" maxSpareThreads="75"      
  3.                enableLookups="false" redirectPort="8443" acceptCount="100"      
  4.                debug="0" connectionTimeout="20000"       
  5.                disableUploadTimeout="true" /> 

關鍵在于,筆者所在的支付平臺服務化架構中,使用了兩套服務化框架,一個是基于dubbo的框架,一個是點對點的RPC,用來緊急情況下dubbo服務出現問題,服務降級使用。

每個服務都配置了點對點的RPC服務,并且獨享一個線程池:

  1. <Connector port="8090"      
  2.                maxThreads="800" minSpareThreads="25" maxSpareThreads="75"      
  3.                enableLookups="false" redirectPort="8443" acceptCount="100"      
  4.                debug="0" connectionTimeout="20000"       
  5.                disableUploadTimeout="true" /> 

由于我們在對dubbo服務框架進行定制化的時候,設計了自動降級原則,如果dubbo服務負載變高,會自動切換到點對點的RPC框架,這也符合微服務的失效轉移原則,但是設計中沒有進行全面的考慮,一旦一部分服務切換到了點對點的RPC,而一部分的服務沒有切換,就導致兩個現場池都被撐滿,于是超過了1024的限制,就出了問題。

到這里,我們基本可以驗證,問題的根源是日志切割導致IO負載增加,然后阻塞線程池,最后發生OOM:unable to create new native thread。

剩下的任務就是最小化重現的問題,通過實踐來驗證問題的原因。我們與性能壓測部門溝通,提出壓測需求:

  1. Tomcat線程池最大設置為1500.
  2. 操作系統允許的最大用戶進程數1024.
  3. 在給服務加壓的過程中,需要人工制造繁忙的IO操作,IO等待不得低于50%。

經過壓測壓測部門的一下午努力,環境搞定,結果證明完全可以重現此問題。

最后,與所有相關部門討論和復盤,應用解決方案,解決方案包括:

  1. 全部應用改成按照小時切割,或者直接使用log4j的日志滾動功能。
  2. Tomcat線程池的線程數設置與操作系統的線程數設置不合理,適當的減少Tomcat線程池線程數量的大小。
  3. 升級log4j日志,使用logback或者log4j2。

這次OOM問題的可以歸結為“多個因、多個果、多臺機器、多個服務池、不同時間”,針對這個問題,與運維部、監控部和性能壓測部門的同事奮斗了幾天幾夜,終于通過在線上抓取信息、分析問題、在性能壓測部門同事的幫助下,最小化重現問題并找到問題的根源原因,最后,針對問題產生的根源提供了有效的方案。

3. 與監控同事現場編寫的腳本

本節提供一個筆者在實踐過程中解決OOM問題的一個簡單腳本,這個腳本是為了解決OOM(unable to create native thread)的問題而在問題機器上臨時編寫,并臨時使用的,腳本并沒有寫的很專業,筆者也沒有進行優化,保持原汁原味的風格,這樣能讓讀者有種身臨其境的感覺,只是為了抓取需要的信息并解決問題,但是在線上問題十分火急的情況下,這個腳本會有大用處。

  1. #!/bin/bash 
  2.  
  3. ps -Leo pid,lwp,user,pcpu,pmem,cmd >> /tmp/pthreads.log 
  4. echo "ps -Leo pid,lwp,user,pcpu,pmem,cmd >> /tmp/pthreads.log" >> /tmp/pthreads.log 
  5. echo `date` >> /tmp/pthreads.log 
  6. echo 1 
  7.  
  8. pid=`ps aux|grep tomcat|grep cwh|awk -F ' ' '{print $2}'
  9. echo 2 
  10.  
  11. echo "pstack $pid >> /tmp/pstack.log" >> /tmp/pstack.log 
  12. pstack $pid >> /tmp/pstack.log 
  13. echo `date` >> /tmp/pstack.log 
  14. echo 3 
  15.  
  16. echo "lsof >> /tmp/sys-o-files.log" >> /tmp/sys-o-files.log 
  17. lsof >> /tmp/sys-o-files.log 
  18. echo `date` >> /tmp/sys-o-files.log 
  19. echo 4 
  20.  
  21. echo "lsof -p $pid >> /tmp/service-o-files.log" >> /tmp/service-o-files.log 
  22. lsof -p $pid >> /tmp/service-o-files.log 
  23. echo `date` >> /tmp/service-o-files.log 
  24. echo 5 
  25.  
  26. echo "jstack -l $pid  >> /tmp/js.log" >> /tmp/js.log 
  27. jstack -l -F $pid  >> /tmp/js.log 
  28. echo `date` >> /tmp/js.log 
  29. echo 6  
  30.  
  31. echo "free -m >> /tmp/free.log" >> /tmp/free.log 
  32. free -m >> /tmp/free.log 
  33. echo `date` >> /tmp/free.log 
  34. echo 7 
  35.  
  36. echo "vmstat 2 1 >> /tmp/vm.log" >> /tmp/vm.log 
  37. vmstat 2 1 >> /tmp/vm.log 
  38. echo `date` >> /tmp/vm.log 
  39. echo 8 
  40.  
  41. echo "jmap -dump:format=b,file=/tmp/heap.hprof 2743" >> /tmp/jmap.log 
  42. jmap -dump:format=b,file=/tmp/heap.hprof >> /tmp/jmap.log 
  43. echo `date` >> /tmp/jmap.log 
  44. echo 9 
  45.  
  46. echo end 

如果讀者在線上已經遇到了OOM的問題,可以順著這個看似簡陋而又信息滿滿的Java服務的監控腳本的思路,利用本文提供的各種腳本和命令來深挖問題的根本原因。

點擊《教你如何成為Java的OOM Killer》閱讀原文。

【本文為51CTO專欄作者“李艷鵬”的原創稿件,轉載可通過作者簡書號(李艷鵬)或51CTO專欄獲取聯系】

戳這里,看該作者更多好文

責任編輯:武曉燕 來源: 51CTO專欄
相關推薦

2020-07-08 07:50:50

OOM虛擬機Java

2012-09-27 10:41:26

2019-01-28 11:54:28

程序員技能溝通

2021-02-05 14:56:39

YouTube編程程序員

2019-11-05 08:24:34

JavaOOM快速定位

2020-07-08 09:50:37

Java內存快速定位

2009-06-17 15:18:09

Java環境

2023-10-09 22:44:51

調試代碼

2021-12-10 23:48:19

Java開發技術

2021-09-09 16:32:41

Java泛型框架

2015-10-08 10:04:39

Python高手

2022-10-12 10:30:35

IT思想領袖企業

2014-03-06 10:34:18

RSA2014

2022-05-01 09:23:50

RosedbContributo重構

2011-09-01 15:01:38

網頁設計

2021-02-21 13:49:48

Java程序員開發

2009-06-10 18:11:58

Java高手

2024-10-10 15:32:51

2021-12-06 10:21:50

LinuxDNS 查詢

2010-07-22 13:14:26

telnet mail
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 91精品国产91久久久久游泳池 | 久久精品一二三影院 | 亚洲 中文 欧美 日韩 在线观看 | 精品国产乱码久久久久久丨区2区 | 中文字幕av亚洲精品一部二部 | 一区二区三区四区电影 | 伦理二区 | 人人亚洲 | 91视频网址 | 91精品久久久久久久久 | 欧美精品在线一区二区三区 | av国产在线观看 | av网站在线播放 | 国产精品毛片一区二区在线看 | 99re热这里只有精品视频 | 国产精品.xx视频.xxtv | 99久久婷婷国产综合精品电影 | 中文字幕 欧美 日韩 | 亚洲欧美日韩一区 | 一区欧美 | 国产免费又黄又爽又刺激蜜月al | 日韩播放 | 亚洲综合在线一区二区 | 99精品视频在线观看 | 国产激情一区二区三区 | 亚洲一区二区在线电影 | 精品区一区二区 | 久久精品美女 | 最新国产精品精品视频 | 欧美一级免费看 | 欧美视频福利 | 国产精品久久久久一区二区三区 | 欧美一区二区在线播放 | 99精品免费久久久久久日本 | 欧美日本久久 | 91av导航| 精品欧美乱码久久久久久 | 欧美成人精品一区 | 91在线观看视频 | 欧美黑人体内she精在线观看 | 中文字幕一区二区三区在线乱码 |