JVM異常之:棧溢出StackOverflowError


  在java虛擬機規范中,虛擬機棧和本地方法棧都會出現StackOverflowError和OutofMemoryError,程序計數器是java虛擬機中唯一一塊不會產生error的內存區域。

一、StackOverflowError(棧溢出)

StackOverflowError代表的是,當棧深度超過虛擬機分配給線程的棧大小時就會出現此error。

在eclipse中增加jvm參數見《eclipse調試時增加jvm參數

示例1:

package com.dxz.jvm;

/**
 * @Described:棧層級不足
 * @VM args:-Xss128k
 */
public class StackOverFlow {
    private int i;

    public void plus() {
        i++;
        plus();
    }

    public static void main(String[] args) {
        StackOverFlow stackOverFlow = new StackOverFlow();
        try {
            stackOverFlow.plus();
        } catch (Error e) {
            System.out.println("Error:stack length:" + stackOverFlow.i);
            e.printStackTrace();
        }
    }
}

-vm args-Xss128k  :說明后面是VM的參數,所以后面的其實都是JVM的參數了

結果:

Error:stack length:997 java.lang.StackOverflowError
    at com.dxz.jvm.StackOverFlow.plus(StackOverFlow.java:11)

 示例2:

package com.dxz.jvm;

/**
 * @Described:遞歸Constructer
 * @VM args:-Xss128k
 */
public class StackOverFlow2 {

    public class OneObject {
        OneObject oneObject = new OneObject();
    }

    public static void main(String[] args) {
        StackOverFlow2 stackOverFlow2 = new StackOverFlow2();
        try {
            OneObject oneObject = stackOverFlow2.new OneObject();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

 

結果:

Exception in thread "main" java.lang.StackOverflowError
    at com.dxz.jvm.StackOverFlow2$OneObject.<init>(StackOverFlow2.java:10)

 

反編譯代碼:

package com.dxz.jvm;

public class StackOverFlow2
{
  public static void main(String[] args)
  {
    StackOverFlow2 stackOverFlow2 = new StackOverFlow2();
    try
    {
      StackOverFlow2 tmp13_12 = stackOverFlow2; tmp13_12.getClass(); OneObject localOneObject = new OneObject();
    } catch (Exception e) {
      e.printStackTrace();
    }
  }

  public class OneObject
  {
    OneObject oneObject = new OneObject(StackOverFlow2.this);

    public OneObject()
    {
    }
  }
}

 看下命令行:

說明:在這里  constructer 中是調用 init , 而 static 是調用 cinit , 固我們如果將自己的對象放入到 static 中是不會造成遞歸的, 而如果將自己本身放到 constructer 中他就會不斷的調用 init ,遞歸並不是馬上返回,而是一層一層的保存在Stack里邊,滿足結束條件后才一層一層的返回。

當Stack滿了就拋出error了。 所以才發生了上面的java.lang.StackOverflowError 溢出錯誤。
注意:是遞歸的錯誤,才出現Stack滿的情況,而無限循環一般不會占用更多的內存或者具體的Stack,只是占cpu而已,所以不會拋此錯誤。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM