1. 程式人生 > >Java調優之jvm和執行緒的記憶體分析

Java調優之jvm和執行緒的記憶體分析

      這幾天因為自己開發的一個網站在768M記憶體的機器上撐不起100多個使用者的執行,因為每個使用者啟用功能後,系統將為每個使用者分配8個左右的獨立執行緒,我的這篇文章http://www.mzone.cc/article/311.html也有介紹的。在記憶體小的機器上經常出現的問題就是Cann’t allocate memory和OutOfMemoryError錯誤,這個要從jvm的記憶體結構來進行分析了。在jvm記憶體調整過程中,我們經常使用的引數就是:

  1. -Xms 為jvm啟動時分配的記憶體,比如-Xms200m,表示分配200M
  2. -Xmx 為jvm執行過程中分配的最大記憶體,比如-Xms500m,表示jvm程序最多隻能夠佔用500M記憶體
  3. -Xss 為jvm啟動的每個執行緒分配的記憶體大小,預設JDK1.4中是256K,JDK1.5+中是1M

      一般jvm出現Cannt’ allocate memory的錯誤就是機器的記憶體不夠,導致系統無法為jvm分配給定的記憶體,這個在啟動時猶未突出,所以會在啟動引數中設定-Xms來指定;而OutOfMemoryError錯誤則一般會在系統執行一段情況後出現,絕大部分也是機器記憶體不夠或是JVM本身的記憶體空間已被用盡,這時就要根據情況進行調整了,如果是JVM本身的記憶體空間用盡,則需要調整-Xmx引數來分類jvm的可用記憶體,如果是機器記憶體不夠則要增加記憶體或是調優程式了。

      上面兩個引數主要是來設定jvm的最小可用記憶體和最大可用記憶體,屬於程序級別的記憶體控制。對於java中的執行緒,我之前的理解一直是在java中new新執行緒的時候是直接使用jvm的記憶體,可實際情況卻不是這樣的。在java中每個執行緒需要分配執行緒記憶體,用來儲存自身的執行緒變數,在jdk1.4中每個執行緒是256K的記憶體,在jdk1.5中每個執行緒是1M的記憶體,jdk1.6中不太清楚,估計也是1M。在java中每new一個執行緒,jvm都是向作業系統請求new一個本地執行緒,此時作業系統會使用剩餘的記憶體空間來為執行緒分配記憶體,而不是使用jvm的記憶體。這樣,當作業系統的可用記憶體越少,則jvm可用建立的新執行緒也就越少,舉個例子如下:

Total Memory -Xms -Xmx -Xss Spare Memory JDK Thread Count
1024M 256M 256M 256K 768M 1.4 3072
1024M 256M 256M 256K 768M 1.5 768

      上面的表格只是大致的估計了下在特定記憶體條件下可以在java中建立的最大執行緒數。隨著-Xmx的加大,空閒的記憶體數就更少,那麼可以建立的執行緒也就更少,同時在JDK1.4和1.5版本不同下,可建立的執行緒數也會根據每個執行緒的記憶體大小不同而不同。

      其實只要我們瞭解了JVM的記憶體大小指定以及java中執行緒的記憶體模型,基本上我們就可以很好的控制如何在java中使用執行緒和避免記憶體溢位或錯誤的問題了。