精华内容
下载资源
问答
  • 2021-02-12 09:48:51

    1、 内存溢出的原因是什么?

    内存溢出是由于没被引用的对象(垃圾)过多造成JVM没有及时回收,造成的内存溢出。如果出现这种现象可行代码排查:

    一)是否App中的类中和引用变量过多使用了Static修饰 如public staitc Student s;在类中的属性中使用 static修饰的最好只用基本类型或字符串。如public static int i = 0; //public static String str;

    二)是否App中使用了大量的递归或无限递归(递归中用到了大量的建新的对象)

    三)是否App中使用了大量循环或死循环(循环中用到了大量的新建的对象)

    四)检查App中是否使用了向数据库查询所有记录的方法。即一次性全部查询的方法,如果数据量超过10万多条了,就可能会造成内存溢出。所以在查询时应采用“分页查询”。

    五)检查是否有数组,List,Map中存放的是对象的引用而不是对象,因为这些引用会让对应的对象不能被释放。会大量存储在内存中。

    六)检查是否使用了“非字面量字符串进行+”的操作。因为String类的内容是不可变的,每次运行"+"就会产生新的对象,如果过多会造成新String对象过多,从而导致JVM没有及时回收而出现内存溢出。

    如String s1 = "My name";

    String s2 = "is";

    String s3 = "xuwei";

    String str = s1 + s2 + s3 +.........;这是会容易造成内存溢出的

    但是String str =  "My name" + " is " + " xuwei" + " nice " + " to " + " meet you"; //但是这种就不会造成内存溢出。因为这是”字面量字符串“,在运行"+"时就会在编译期间运行好。不会按照JVM来执行的。

    在使用String,StringBuffer,StringBuilder时,如果是字面量字符串进行"+"时,应选用String性能更好;如果是String类进行"+"时,在不考虑线程安全时,应选用StringBuilder性能更好。

    七)使用 DDMS工具进行查找内存溢出的大概位置

    2、栈溢出的原因

    一)、是否有递归调用

    二)、是否有大量循环或死循环

    三)、全局变量是否过多

    四)、 数组、List、map数据是否过大

    五)使用DDMS工具进行查找大概出现栈溢出的位置

    更多相关内容
  • JAVA栈溢出

    2021-02-12 09:48:47
    Java栈溢出小记今天偶然有人问起如何在编写Java代码使其在运行时抛出栈溢出异常,看似简单的问题涉及到了Java虚拟机的知识,特记录于此文。Java虚拟机结构简介根据《Java虚拟机规范》(The Java Virtual Machine ...

    5dde8f08481c1.png

    Java栈溢出小记

    今天偶然有人问起如何在编写Java代码使其在运行时抛出栈溢出异常,看似简单的问题涉及到了Java虚拟机的知识,特记录于此文。

    Java虚拟机结构简介

    根据《Java虚拟机规范》(The Java Virtual Machine Specification)对于Java虚拟机运行时数据区域(Run-Time Data Areas)的描述,虚拟机运行时的描述,其构成图如下所示:

    5dde8f08481c1.png

    图中,PC寄存器、Java虚拟机栈及本地方法栈为各线程私有,方法区(包括运行时常量取)及堆为线程间共享的存储空间。针对问题提出的栈溢出,有两个区域与其相关,包括Java虚拟机栈及本地方法栈。查阅《Java虚拟机规范》,针对栈溢出有如下两段描述:

    对于Java虚拟机栈The following exceptional conditions are associated with Java Virtual Machine stacks:If the computation in a thread requires a larger Java Virtual Machine stack than is permitted, the Java Virtual Machine throws a StackOverflowError.

    If Java Virtual Machine stacks can be dynamically expanded, and expansion is attempted but insufficient memory can be made available to effect the expansion, or if insufficient memory can be made available to create the initial Java Virtual Machine stack for a new thread, the Java Virtual Machine throws an OutOfMemoryError.

    对于本地方法栈The following exceptional conditions are associated with native method stacks:If the computation in a thread requires a larger native method stack than is permitted, the Java Virtual Machine throws a StackOverflowError.

    If native method stacks can be dynamically expanded and native method stack expansion is attempted but insufficient memory can be made available, or if insufficient memory can be made available to create the initial native method stack for a new thread, the Java Virtual Machine throws an OutOfMemoryError.

    由此可见对于Java虚拟机栈与本地方法栈都定义了相似的两种溢出:线程请求栈上分配内存时,内存不足:此溢出一般出现在线程递归调用方法时。在线程调用方法时虚拟机创建栈帧保存方法调用信息,在方法调用完成后销毁栈帧释放存储,如果在方法调用过程中无法创建栈帧则会报出StackOverflowError异常。

    动态扩展栈或线程创建时无法分配足够内存:此溢出一般出现在创建新的线程时。创建新的线程,需要在栈上为其分配存储,如果此时栈上存储不足以分配则会报出OutOfMemoryError异常。

    代码实现

    以下代码在Mac版JDK8中实现及运行,由于HotSpot实现中没有分Java虚拟机栈及本地方法栈-Xss,后续实验均设置-Xss1M,使用Junit4进行测试

    分配栈帧失败(StackOverflowError)

    代码为:1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16public class{

    public void callMyself(int depth){

    System.out.println(depth);

    callMyself(++depth);

    }

    }

    public class StackOverflowTest{

    public void callMyself() throws Exception{

    StackOverflow overflow = new StackOverflow();

    overflow.callMyself(0);

    }

    }

    最终会抛出java.lang.StackOverflowError,且最终能够达到的栈深度主要与栈内存最大大小与栈帧中局部变量占用的空间有关。使用如下代码最大深度会明显变小1

    2

    3

    4

    5

    6

    7

    8public class{

    public void callMyself(int depth){

    int a,b,c,d,e,f,g,h,i,j,k;

    System.out.println(depth+"|");

    callMyself(++depth);

    }

    }

    为线程分配栈上内存失败(OutOfMemoryError)

    代码为:1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20public class OutOfMemory{

    public void createThread(){

    while (true) {

    Thread t = new Thread(() -> {

    while (true) {

    System.out.println(System.currentTimeMillis());

    }

    });

    t.start();

    }

    }

    }

    public class OutOfMemoryTest{

    public void createThread() throws Exception{

    OutOfMemory outOfMemory = new OutOfMemory();

    outOfMemory.createThread();

    }

    }

    最终会抛出OutOfMemoryError。

    针对于OutOfMemoryError的补充

    在HotSpot虚拟机实现中,对于Java线程的创建是映射到操作系统线程中的,如果无法创建操作系统线程也会抛出异常,具体为:java.lang.OutOfMemoryError: unable to create new native thread。

    通过实验在MacOS中,一般小于2048(多次测试为2023),因为默认Mac每个进程最多分配的线程数为2048。可使用sysctl kern.num_taskthreads命令进行查询。如果需要突破限制可以参考官方解决方案。

    在centOS中实验发现max_user_processes及stack size参数都会限制各进程的线程数量。

    参考文献

    [1] 周志明.深入理解Java虚拟机[M].北京:机械工业出版社,53

    展开全文
  • java栈溢出

    2019-03-04 16:51:26
    JVM异常之:栈溢出StackOverflowError  在java虚拟机规范中,虚拟机栈和本地方法栈都会出现StackOverflowError和OutofMemoryError,程序计数器是java虚拟机中唯一一块不会产生error的内存区域。 一、StackOverflow...

    JVM异常之:栈溢出StackOverflowError
      在java虚拟机规范中,虚拟机栈和本地方法栈都会出现StackOverflowError和OutofMemoryError,程序计数器是java虚拟机中唯一一块不会产生error的内存区域。

    一、StackOverflowError(栈溢出)
    StackOverflowError代表的是,当栈深度超过虚拟机分配给线程的栈大小时就会出现此error。

    通过参数-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的参数了

    结果:

    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而已,所以不会抛此错误。

    展开全文
  • 1、 内存溢出的原因是什么? 内存溢出是由于没被引用的对象(垃圾)过多造成JVM没有及时回收,造成的内存溢出。如果出现这种现象可行代码排查: 一)是否App中的类中和引用变量过多使用了Static修饰 如public staitc...

    1、 内存溢出的原因是什么?

    内存溢出是由于没被引用的对象(垃圾)过多造成JVM没有及时回收,造成的内存溢出。如果出现这种现象可行代码排查:

    一)是否App中的类中和引用变量过多使用了Static修饰 如public staitc Student s;在类中的属性中使用 static修饰的最好只用基本类型或字符串。如public static int i = 0; //public static String str;
    二)是否App中使用了大量的递归或无限递归(递归中用到了大量的建新的对象)
    三)是否App中使用了大量循环或死循环(循环中用到了大量的新建的对象)
    四)检查App中是否使用了向数据库查询所有记录的方法。即一次性全部查询的方法,如果数据量超过10万多条了,就可能会造成内存溢出。所以在查询时应采用“分页查询”。
    五)检查是否有数组,List,Map中存放的是对象的引用而不是对象,因为这些引用会让对应的对象不能被释放。会大量存储在内存中。
    六)检查是否使用了“非字面量字符串进行+”的操作。因为String类的内容是不可变的,每次运行"+"就会产生新的对象,如果过多会造成新String对象过多,从而导致JVM没有及时回收而出现内存溢出。

    如String s1 = “My name”;
    String s2 = “is”;
    String s3 = “xuwei”;
    String str = s1 + s2 + s3 +…;这是会容易造成内存溢出的
    但是String str = “My name” + " is " + " xuwei" + " nice " + " to " + " meet you"; //但是这种就不会造成内存溢出。因为这是”字面量字符串“,在运行"+"时就会在编译期间运行好。不会按照JVM来执行的。

    在使用String,StringBuffer,StringBuilder时,如果是字面量字符串进行"+“时,应选用String性能更好;如果是String类进行”+"时,在不考虑线程安全时,应选用StringBuilder性能更好。

    七)使用 DDMS工具进行查找内存溢出的大概位置

    class Solution {
    	private String aString = "abc";
    
    	public void add() {
    		while (true) {
    			aString += aString;
    		}
    	}
    
    	public static void main(String[] args) {
    		new Solution().add();
    	}
    }
    

    2、栈溢出的原因

    一)、是否有递归调用
    二)、是否有大量循环或死循环
    三)、全局变量是否过多
    四)、 数组、List、map数据是否过大
    五)使用DDMS工具进行查找大概出现栈溢出的位置

    栈溢出的例子:

    class Solution {
    	int count = 0;
    	public void add() {
    		System.out.println(count++);
    		add();
    	}
    
    	public static void main(String[] args) {
    		new Solution().add();
    	}
    }
    
    展开全文
  • 为什么运行如下程序 , 方法sum2 不会导致栈溢出, 方法sum 会导致栈溢出?--------output-----------32004000java.lang.StackOverflowErrorException in thread "main"--------output-----------public class ...
  • 栈溢出内存溢出Out Of Memory(OOM):指申请内存时,没有足够的内存供其使用。内存泄露Memory Leak:内存泄露,程序申请内存后,无法释放已申请的内存空间。内存泄露的堆积,浪费了内存空间,可能会造成OOM.分析工具...
  • java内存溢出 原因与排查方法 1、 内存溢出的原因是什么? 内存溢出是由于没被引用的对象(垃圾)过多造成JVM没有及时回收,导致剩余的内存不够用,造成的内存溢出。如果出现这种现象可行代码排查: 一)是否应用...
  • 堆溢出:/*** @author LXA* 堆溢出*/public class Heap{public static void main(String[] args){ArrayList list=new ArrayList();...}}}报错:java.lang.OutOfMemoryError: Java heap space栈溢出...
  • Java 模拟栈溢出错误 栈,也叫栈内存 主管程序的运行,生命周期和栈线程同步 线程结束,栈内存也就释放了 栈:先进后出,后进先出 栈溢出错误:StackOverflowError java.lang.StackOverflowError:一般出现这个问题...
  • 怎样解决栈溢出

    千次阅读 2021-03-13 15:46:44
    1,什么是栈溢出?由于栈一般默觉得1-2m,一旦出现死循环或者是大量的递归调用,在不断的压栈过程中,造成栈容量超过1m而导致溢出。2,解决方式:方法一:用栈把递归转换成非递归通常,一个函数在调用还有一个函数...
  • java内存溢出和栈溢出

    2018-06-08 00:54:27
     * 栈溢出    * @author feizi    * @time 2015-1-23上午9:13:11    */   public   class  SOFTest {      public   void  stackOverFlowMethod(){   stackOverFlowMethod();   }      ...
  • Java内存溢出与栈溢出分析

    千次阅读 2018-06-14 15:53:18
     * 栈溢出    * @author feizi    * @time 2015-1-23上午9:13:11    */   public   class  SOFTest {      public   void  stackOverFlowMethod(){   stackOverFlowMethod();   }      ...
  • java 内存溢出 栈溢出的原因

    千次阅读 2019-03-04 13:53:06
    内存溢出是由于没被引用的对象(垃圾)过多造成JVM没有及时回收,造成的内存溢出。如果出现这种现象可行代码排查: 一)是否应用中的类中和引用变量过多使用了Static修饰 如public staitc Student s;在类中的属性...
  • Java的一个栈溢出问题

    2021-12-20 10:36:29
    今天,突然想到这样一个问题,以下代码被调用运行时为何会造成栈溢出(StackOverflowError)的错误: public class Constructor { Constructor c = new Constructor(); public static void main(String[] args) { ...
  • 如何解决栈溢出

    千次阅读 2021-03-13 15:47:06
    1,什么是栈溢出?因为栈一般默认为1-2m,一旦出现死循环或者是大量的递归调用,在不断的压栈过程中,造成栈容量超过1m而导致溢出。2,解决方案:方法一:用栈把递归转换成非递归通常,一个函数在调用另一个函数之前,...
  • JVM之栈溢出和堆溢出

    千次阅读 2021-03-08 09:55:49
    jvm堆溢出和栈溢出一、jvm堆溢出1、介绍在jvm运行java程序时,如果程序运行所需要的内存大于系统的堆最大内存(-Xmx),就会出现堆溢出问题。2、案例//介绍:执行该段代码需要大于10m内存空间public classHeadOverflow ...
  • Java解决栈溢出

    千次阅读 2021-02-26 12:50:35
    1,什么是栈溢出?因为栈一般默认为1-2m,一旦出现死循环或者是大量的递归调用,在不断的压栈过程中,造成栈容量超过1m而导致溢出。2,解决方案:方法一:用栈把递归转换成非递归通常,一个函数在调用另一个函数之前,...
  • 模拟Java栈溢出过程

    千次阅读 2019-06-22 15:15:01
    Java栈,是指Java虚拟机栈,本地方法栈; Java虚拟机栈是Java方法执行的内存模型,每个方法执行的同时都会创建一个栈帧用于存储局部变量,操作数栈,动态链接(在一个方法中调用另一个方法),方法出口等信息。每...
  • 说说java栈溢出那些事儿

    千次阅读 2018-08-28 21:58:56
    今天写了一个bug导致出现了栈溢出,出现栈溢出的根本原因是出现了无限次的递归,递归嵌套的层次太多,方法进栈次数太多,导致栈区不足出现StackOverFlow,写代码以来第一次出现这种bug,幸亏自己之前对这方面有了解...
  • 如何构造jvm的堆溢出和栈溢出构造堆溢出和栈溢出Java虚拟机中描述了两种异常:如果线程请求的栈深度大于虚拟机所允许的最大深度,将抛出StackOverflowError异常;—-栈溢出如果在虚拟机中无法申请到足够多的内存空间...
  • 栈溢出的原因在解决栈溢出问题之前,我们首先需要知道一般引起栈溢出的原因,主要有以下几点:是否有递归调用,循环依赖调用是否有大量循环或死循环全局变量是否过多局部变量过大,如:数组、List、Map数据过大问题...
  • Java堆栈溢出

    2021-03-09 09:28:16
    Java堆栈溢出背景知识:栈存放什么:栈存储运行时声明的变量——...栈溢出java.lang.StackOverflowError堆溢出:java.lang.OutOfMemoryError: Java heap space栈溢出实现,可以递归调用方法,这样随着栈深度的增加...
  • Java溢出 JVM运行时分区的堆区是占比最大的,它用来存储对象的,每当我们new一个对象,而且要保证这个对象到GC Roots 那些对象是有路径可达的(不可达就有很大可能性被清除),那么当对象的数量超过最大堆容量后就...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 85,353
精华内容 34,141
关键字:

java栈溢出

java 订阅