java栈溢出是什么原因?java栈溢出模拟示例

TheDisguiser 2020-06-08 21:30:31 java常见问答 7810

Java实现栈时,有时候会在栈中会出现栈溢出异常,小伙伴们知道这都是由于那些原因引起的吗?下面快看小编详细说道说道吧。

通常来说,栈溢出的原因不外乎就是递归或循环的问题,栈中出错最多的就是这两个家伙了。在java中,我们一般可以通过以下原因来排查栈溢出原因。

1)、递归调用是否正确

2)、循环是否过多或出现死循环

3)、全局变量定义是否过多

4)、 数组、List、map等集合数据是否过大

5)、使用DDMS工具来查找几率出现栈溢出的位置

现在我们来通过以下两个例子来深入了解一下栈溢出的原因吧。

一、StackOverflowError(栈溢出)

当一个栈深度超过虚拟机分配给线程的栈大小时就会出现此error,StackOverflowError。

我们还可以通过参数-XX:+HeapDumpOnOutOfMemoryError 让虚拟机在出现内存溢出异常时Dump 出当前的内存堆转储快照方便我们进行原因解析。

例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参数了。

例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()
        {}
    }
}

命令行:

java栈溢出

以上在我们的constructer 中其实是调用的init 方法, 然static却是调用 cinit方法 , 所以如果我们把自己对象放入到static中是不会造成递归的, 但如果把自己本体放到constructer中它就会不断的调用 init方法 ,因为递归并不是马上就返回的,它会一层一层的保存在Stack里边,直到你满足结束条件后才会一层一层的返回。

当我们的Stack已满时,系统抛出error,java.lang.StackOverflowError 溢出异常就产生了。

以上就是关于栈溢出原因的所有内容了,小伙伴们如果还想要了解更多栈知识常见问题可以关注我们的网站来了解详情。

推荐阅读:

java栈实现方法都有哪些?要怎么实现?

java栈的特点是什么?java的堆和栈的优缺点介绍

简述如何用两个栈实现一个队列?