走自己的路

          路漫漫其修遠(yuǎn)兮,吾將上下而求索

            BlogJava :: 首頁(yè) :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理 ::
            50 隨筆 :: 4 文章 :: 118 評(píng)論 :: 0 Trackbacks

           星期一早上到了公司,據(jù)稱(chēng)產(chǎn)品環(huán)境拋出了最可愛(ài)的異常—OutOfMemory, 它是這樣來(lái)描述他自己的:

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

          而且這位仁兄竟然還堂而皇之地同時(shí)出現(xiàn)在了3個(gè)application里面,所有應(yīng)用全部遭殃。

          那可愛(ài)的OOM是如何產(chǎn)生的呢?直接原因是創(chuàng)建的線(xiàn)程太多了,根本原因是某個(gè)地方的內(nèi)存限制了。

          搜羅了一下在網(wǎng)上找到了一個(gè)計(jì)算公式:

          (MaxProcessMemory - JVMMemory – ReservedOsMemory) / (ThreadStackSize) = Number of threads 

          MaxProcessMemory:進(jìn)程最大的尋址空間,但我想這個(gè)值應(yīng)該也不會(huì)超過(guò)虛擬內(nèi)存和物理內(nèi)存的總和吧。關(guān)于不同系統(tǒng)的進(jìn)程可尋址的最大空間,可參考下面表格:

          Maximum Address Space Per Process

          Operating System

          Maximum Address Space Per Process

          Redhat Linux 32 bit

          2 GB

          Redhat Linux 64 bit

          3 GB

          Windows 98/2000/NT/Me/XP

          2 GB

          Solaris x86 (32 bit)

          4 GB

          Solaris 32 bit

          4 GB

          Solaris 64 bit

          Terabytes

          JVMMemory: Heap + PermGen

          ReservedOSMemoryNative heapJNI

          便可推導(dǎo)出單個(gè)JVM Instance可支持的最大線(xiàn)程數(shù)的估計(jì)值:

          (MaxProcessMemory<固定值> – Xms<初始化值,最小值> – XX:PermSize<初始化值,最小值> – 100m<估算值>) / Xss = Number of threads<最大值>

          在本地(32bit windows)試了試,可達(dá)的線(xiàn)程的最大值差不多就是這個(gè)數(shù),它不受物理內(nèi)存的限制,會(huì)利用虛擬內(nèi)存,從任務(wù)管理器看到memory已經(jīng)是5500 m左右了(開(kāi)了兩個(gè)jvm),我機(jī)器的物理內(nèi)存是2g,也不知道這個(gè)準(zhǔn)不準(zhǔn),后來(lái)還拋出了“unable to create new native thread”的兄弟“Exception in thread "CompilerThread0" java.lang.OutOfMemoryError: requested 471336 bytes for Chunk::new. Out of swap space?“。

          本地測(cè)完了后,就該輪到dev環(huán)境了,linux2.664bit,雙核,8G(虛擬機(jī)),總的物理內(nèi)存是16g。在上面整了一下,創(chuàng)建到了15000多個(gè)線(xiàn)程的時(shí)候掛掉了。此時(shí)其他application也不能創(chuàng)建新的線(xiàn)程,而且db也報(bào)錯(cuò)了,操作系統(tǒng)不能fork新的線(xiàn)程了。這應(yīng)該是操作系統(tǒng)的哪里限制了新線(xiàn)程的創(chuàng)建,

          ·         max threadlinux2.6似乎是32000

          ·         最大可用內(nèi)存:物理內(nèi)存+虛擬內(nèi)存

          ·         配置,在linux可以限制可用資源的大小,show一下這些參數(shù)

          core file size          (blocks, -c) 0

          data seg size           (kbytes, -d) unlimited

          file size               (blocks, -f) unlimited

          pending signals                 (-i) 1024

          max locked memory       (kbytes, -l) 32

          max memory size         (kbytes, -m) unlimited

          open files                      (-n) 65536

          pipe size            (512 bytes, -p) 8

          POSIX message queues     (bytes, -q) 819200

          stack size              (kbytes, -s) 10240

          cpu time               (seconds, -t) unlimited

          max user processes              (-u) 16384

          virtual memory          (kbytes, -v) unlimited

          file locks                      (-x) unlimited

          為了進(jìn)一步確定在linux上一個(gè)jvm因?yàn)檫_(dá)到了最大尋址空間OOM了,不會(huì)影響其他jvm,我在Linux做了進(jìn)一步測(cè)試,一開(kāi)始用Sun文檔中說(shuō)的最大尋址空間3G試了一下,發(fā)現(xiàn)根本不對(duì),達(dá)到了3G后還是非常high地在創(chuàng)建新的線(xiàn)程。于是出動(dòng)超級(jí)無(wú)敵變態(tài)的JVM初始化配置。

          oracle   27408 27017 12 13:45 ?        00:00:07 /home/oracle/ias1013/FWAPP/FWDev/jdk/bin/java -server -Xmx4096m -Xms4096m -XX:+HeapDumpOnOutOfMemoryError -XX:PermSize=4096m -XX:MaxPermSize=4096m -XX:HeapDumpPath=/home/oracle/ias1013/FWAPP/FWDev/j2ee/OC4J_OOMTest/workEnv/log -Xss100m

          結(jié)果在create 3379個(gè)線(xiàn)程后,“unable to create new native thread”出現(xiàn)了,這時(shí)其他jvm都是可以create新線(xiàn)程的。如果按照上面公式計(jì)算,linux 64bit2.6kernel,它的最大尋址空間肯定超過(guò)了300g,當(dāng)然應(yīng)該還沒(méi)有達(dá)到可用內(nèi)存的限制,因?yàn)槠渌?/span>JVM還create新線(xiàn)程。

          我還懷疑是不是oracle application server上的某個(gè)配置參數(shù)限制了總的線(xiàn)程數(shù),影響了所有application,但我們的產(chǎn)品環(huán)境一個(gè)application就是一個(gè)單獨(dú)的application server。

          現(xiàn)在基本上可以確定是操作系統(tǒng)哪里設(shè)置錯(cuò)了,我想System team的帥哥們應(yīng)該把產(chǎn)品環(huán)境的某個(gè)參數(shù)配置錯(cuò)了,系統(tǒng)本身的影響肯定不會(huì)有了,因?yàn)楫a(chǎn)品環(huán)境上我們只create800左右個(gè)線(xiàn)程,就OOM了,那應(yīng)該就是配置的問(wèn)題了,懷疑的參數(shù)有下面四個(gè)

          max user processes              (-u) 2048

          virtual memory          (kbytes, -v) unlimited

          max memory size         (kbytes, -m) unlimited

          stack size              (kbytes, -s) 10240

          最后發(fā)現(xiàn)只有max user processes virtual memory對(duì)總的線(xiàn)程數(shù)有影響,我把max user processes降到2048后,發(fā)現(xiàn)此時(shí)只能創(chuàng)建 2000左右個(gè)線(xiàn)程了(Xms64m, Xss1m),進(jìn)一步地把virtual memory下調(diào)到2048000K發(fā)現(xiàn)能創(chuàng)建的就更少了1679Xms64m, Xss1m),而它只會(huì)對(duì)當(dāng)前shell起作用,而多個(gè)application server應(yīng)該是不同的shell,所以他是打醬油的。另外兩個(gè)參數(shù)好像就是來(lái)做做俯臥撐的,操作系統(tǒng)stack size是不應(yīng)該會(huì)有什么影響,我們把它上調(diào)到102400,還是可以創(chuàng)建2000左右的線(xiàn)程數(shù)(max user processes),因?yàn)?/span>java有自己的線(xiàn)程模型,它的棧的大小是用Xss來(lái)控制的。Max memory size不知道是啥東東,照理說(shuō)如果是最大內(nèi)存應(yīng)該不會(huì)只在旁邊做俯臥撐,那這個(gè)參數(shù)到底是春哥還是曾哥,查了一下man ulimit,有下面解釋

                        -a     All current limits are reported

                        -c     The maximum size of core files created

                        -d     The maximum size of a process data segment

                        -f     The maximum size of files created by the shell

                        -l     The maximum size that may be locked into memory

                        -m     The maximum resident set size (has no effect on Linux)

                        -n     The maximum number of open file descriptors (most systems do not allow this value to be set)

                        -p     The pipe size in 512-byte blocks (this may not be set)

                        -s     The maximum stack size

                        -t     The maximum amount of cpu time in seconds

                        -u     The maximum number of processes available to a single user

                        -v     The maximum amount of virtual memory available to the shell

          Has no effect on Linux”就足以證明它確實(shí)只是來(lái)做做俯臥撐的。最后查出只有“max user processes”會(huì)對(duì)所有application能創(chuàng)建總的線(xiàn)程數(shù)有限制。



          posted on 2009-09-25 10:55 叱咤紅人 閱讀(34943) 評(píng)論(10)  編輯  收藏 所屬分類(lèi): J2SE and JVM

          評(píng)論

          # re: 剝下“java.lang.OutOfMemoryError: unable to create new native thread”的外衣[未登錄](méi) 2010-01-19 17:16 菜鳥(niǎo)
          我最近總也是碰見(jiàn)OOM(Exception in thread "CompilerThread0" java.lang.OutOfMemoryError: requested 1056888 bytes for Chunk::new. Out of swap space?)
          不知道大俠能否指點(diǎn)下偶?

          1、服務(wù)器硬件配置如下:
          Type IBM X3850
          Processor Details 2132 MHz * 16
          Memory 16G
          操作系統(tǒng)是RedHat企業(yè)版5.0,64位服務(wù)器

          2、我使用的JDK是jdk-1_5_0_12-linux-i586,應(yīng)用服務(wù)器是Weblogic 9.2,weblogic服務(wù)器setDomain.sh文件的參數(shù)配置如下:
          # PATCH_LIBPATH=[myPatchLibpath] (unix)
          # PATCH_PATH=[myPatchPath] (unix)

          . ${WL_HOME}/common/bin/commEnv.sh

          WLS_HOME="${WL_HOME}/server"
          export WLS_HOME

          WLI_HOME="${WL_HOME}/integration"
          export WLI_HOME

          MEM_ARGS="-Xms3072m -Xmx3072m"
          export MEM_ARGS

          if [ "${JAVA_VENDOR}" = "Sun" ] ; then
          if [ "${PRODUCTION_MODE}" = "" ] ; then
          MEM_DEV_ARGS="-XX:CompileThreshold=8000 -XX:PermSize=96m -XX:+UseParallelGC "
          export MEM_DEV_ARGS
          fi
          fi

          # Had to have a separate test here BECAUSE of immediate variable expansion on windows

          if [ "${JAVA_VENDOR}" = "Sun" ] ; then
          MEM_ARGS="${MEM_ARGS} ${MEM_DEV_ARGS} -XX:MaxPermSize=256m"
          export MEM_ARGS
          fi

            回復(fù)  更多評(píng)論
            

          # re: 剝下“java.lang.OutOfMemoryError: unable to create new native thread”的外衣[未登錄](méi) 2010-01-19 17:17 菜鳥(niǎo)
          我的郵箱是ooxoo024@hotmail.com,請(qǐng)大俠指點(diǎn)下,先謝謝了。  回復(fù)  更多評(píng)論
            

          # re: 剝下“java.lang.OutOfMemoryError: unable to create new native thread”的外衣 2010-01-20 07:42 叱咤紅人
          帥哥,
          1.用ulimit看一下,虛擬內(nèi)存是否做了限制。這個(gè)異常我測(cè)試下來(lái)是出現(xiàn)在當(dāng)總內(nèi)存(物理內(nèi)存+虛擬內(nèi)存)不夠的情況下。
          2.用profile工具或者gc log看一下內(nèi)存的使用情況。看程序中是否有內(nèi)存溢出的風(fēng)險(xiǎn)。
          3.出問(wèn)題時(shí)系統(tǒng)中的線(xiàn)程使用情況。kill -3 或者用TDA.  回復(fù)  更多評(píng)論
            

          # re: 剝下“java.lang.OutOfMemoryError: unable to create new native thread”的外衣 2010-03-22 18:51 zhaixf
          帥哥,我也做了下相應(yīng)的測(cè)試,發(fā)現(xiàn)公式中的:
          便可推導(dǎo)出單個(gè)JVM Instance可支持的最大線(xiàn)程數(shù)的估計(jì)值:
          (MaxProcessMemory<固定值> – Xms<初始化值,最小值> – XX:PermSize<初始化值,最小值> – 100m<估算值>) / Xss = Number of threads<最大值>
          Xms不會(huì)影響創(chuàng)建線(xiàn)程的個(gè)數(shù),起作用的應(yīng)該是:-Xmx
          其他地方和我想的基本一致,但是我在測(cè)試過(guò)程中遇到了比較奇怪的問(wèn)題,沒(méi)有辦法解釋?zhuān)合旅媸俏覝y(cè)試的情況,重點(diǎn)關(guān)注“-Xmx1692m”,似乎作為了一個(gè)分隔線(xiàn),之上的也能用公式解釋?zhuān)碌囊材苡霉浇忉尅?

          -Xms3060m -Xmx3060m
          -Xss2048k (thread :94)

          -Xms2560m -Xmx2560m
          -Xss2048k (thread :157)

          -Xms2048m -Xmx2048m
          -Xss2048k (thread :221)
          -Xss1024k (thread :598)

          -Xms1792m -Xmx1792m
          -Xss1024k (thread :683)

          -Xms1692m -Xmx1692m
          -Xss1024k (thread :49)(進(jìn)程自己結(jié)束)

          -Xms1560m -Xmx1560m
          -Xss2048k (thread :31)(進(jìn)程自己結(jié)束hs_err_pid24865.log)

          -Xms1536m -Xmx1536m
          -Xss2048k (thread :34)(進(jìn)程自己結(jié)束hs_err_pid24865.log)
          -Xss1024k(thread :100)

          -Xms1024m -Xmx2048m
          -Xss2048k (thread :221)

          -Xms1048m -Xmx1048m
          -Xss2048k (thread :95)

          -Xms560m -Xmx1152m
          -Xss2048k(thread :82)
          -Xss1024k(thread :228)

          -Xms1048m -Xmx3560m
          -Xss2048k (thread :32)(進(jìn)程自己結(jié)束)  回復(fù)  更多評(píng)論
            

          # re: 剝下“java.lang.OutOfMemoryError: unable to create new native thread”的外衣 2010-03-22 22:02 ldd600
          @zhaixf
          1. 和Xss值有關(guān),你的結(jié)果也可以說(shuō)明這一點(diǎn),或者您可將Xss設(shè)置的變態(tài)一點(diǎn)
          2. 您用的是32位還是64位系統(tǒng),您的虛擬內(nèi)存是多大,虛擬內(nèi)存還受其他程序的影響。
            回復(fù)  更多評(píng)論
            

          # re: 剝下“java.lang.OutOfMemoryError: unable to create new native thread”的外衣 2010-11-17 11:57 higkoo
          不錯(cuò),頂起!  回復(fù)  更多評(píng)論
            

          # re: 剝下“java.lang.OutOfMemoryError: unable to create new native thread”的外衣 2013-02-25 14:52 excite
          數(shù)據(jù)記錄的很詳細(xì),很有參考價(jià)值!  回復(fù)  更多評(píng)論
            

          # re: 剝下“java.lang.OutOfMemoryError: unable to create new native thread”的外衣 2013-04-02 15:17 wxylion1
          good job  回復(fù)  更多評(píng)論
            

          # re: 剝下“java.lang.OutOfMemoryError: unable to create new native thread”的外衣[未登錄](méi) 2013-05-15 17:09 Ryan
          很好,呵呵有價(jià)值的文章。  回復(fù)  更多評(píng)論
            

          # re: 剝下“java.lang.OutOfMemoryError: unable to create new native thread”的外衣[未登錄](méi) 2015-12-09 15:37 呵呵
          除了公式外,還和max user processes 限定有關(guān)吧?  回復(fù)  更多評(píng)論
            

          主站蜘蛛池模板: 临朐县| 钦州市| 鄂伦春自治旗| 车险| 当阳市| 股票| 安徽省| 广水市| 天等县| 施秉县| 鲁甸县| 怀仁县| 永和县| 阳原县| 尼木县| 息烽县| 建德市| 广丰县| 集贤县| 邯郸县| 崇阳县| 扎鲁特旗| 大埔县| 体育| 漠河县| 永州市| 郁南县| 苗栗市| 闸北区| 厦门市| 新津县| 噶尔县| 嘉峪关市| 阜新市| 灵宝市| 丰城市| 普兰县| 宜宾市| 阳春市| 宜黄县| 瑞安市|