1. 程式人生 > >JVM學習筆記三_異常初步

JVM學習筆記三_異常初步

Java堆溢位

說明:Java堆用於儲存物件例項,只要不斷建立物件。且保證GC Roots到物件之間有可達的路徑來避免垃圾回收機制來清除這些物件,那麼在物件數量達到最大堆的容量限制之後就會產生記憶體溢位異常。

重點:模擬不斷建立物件簡單,但是需要保證創建出來的物件不被GC掉。同樣的,出錯時可能的狀況也是如此,就是物件被創建出但是未被及時回收。-Xms堆最小值 -Xmx堆最大值。

虛擬機器棧和本地方法棧溢位

丟擲兩種異常:

1. 如果執行緒請求的棧深度大於虛擬機器所允許的最大深度,將丟擲StackOverflowError異常。

2. 如果虛擬機器在擴充套件棧時,無法申請到足夠的記憶體空間,則丟擲OutOfMemoryError異常。

說明:單執行緒的情況下,不論是棧幀太大還是虛擬機器的棧記憶體太小,當記憶體無法正常分配時,都會丟擲StackOverflowError異常。

      但是如果在使用多執行緒的情況下,會產生OutOfMemoryError異常。每個執行緒不斷去建立執行緒,那麼當到達上限是,就會丟擲OutOfMemoryError異常。而且棧幀越大,執行緒上限將會越小。

   原因就是:作業系統對於每個程序,分配的記憶體都是有限制的。虛擬機器引數控制了Java堆和方法區的記憶體的最大值。所以剩餘記憶體為 程序分配的最大記憶體(M) 減去 最大堆的記憶體Xmx,再減去最大方法區的MaxPermSize,

   程式計數器記憶體很小可忽略。剩下的記憶體是由虛擬機器棧和本地方法棧分得的。每個執行緒分配到的棧容量越大,那麼可建立的執行緒數量就會很小,建立執行緒時就會越容易把記憶體耗盡。

一般情況下 棧深度可以達到1000到2000。但是如果建立了過多的執行緒導致了記憶體溢位,在不能減少執行緒和使用64位虛擬機器的情況下,只能通過減少最大堆和減少棧容量來換取更多執行緒。

 方法區和執行時常量區溢位

 執行時常量池是方法區的一部分,在JDK1.6及以前的版本中,因為常量池分配在永久代中,我們可以通過-XX:PermSize和-XX:MaxPermSize來限制方法區大小,從而間接限制其中常量池的容量。

 程式碼如下:

1 public static void main(String[] args) {
2     List<String> list = new ArrayList<String>();
3     int i = 1;
4     while (true) {
5         ist.add(String.valueOf(i++).intern());
6     }
7 }

會丟擲OutOfMemoryError異常。

但是在JDK1.7以後,while迴圈會一直進行下去。

方法區的用於儲存Class相關的資訊,比如類名、訪問修飾符、常量池、欄位描述、方法描述等。對於此區域的測試,可以產生大量的類去填滿方法區,直到溢位。