精华内容
下载资源
问答
  • 2021-11-06 18:25:15

    JVN存储分区

    JVM存储分区分为:堆、栈、方法区、程序计数器、本地方法栈这五部分。

    堆:java所有线程共享的内存区域,在虚拟机启动时创建,几乎所有对象实例都放在这里,因此该区域经常发生垃圾回收。

    栈:每个线程包含一个栈区,主要保存基础数据类型的对象、自定义对象指针、方法的执行过程、返回值等信息。同时存储运算结果、运算操作数,最典型例如:计算表达式,程序中所有计算结果都是通过操作数栈完成的。

    方法区:方法区用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译后的代码等数据。

    程序计数器:包含当前正在执行的指令的地址(位置)。当每个指令被获取,程序计数器的存储地址加一。在每个指令被获取之后,程序计数器指向顺序中的下一个指令。

    本地方法栈:虚拟机栈为虚拟机执行Java方法(也就是字节码)服务,而本地方法栈则是为虚拟机使用到的Native方法服务。

    原因定位:

    1、有递归调用,且递归层级过深;

    2、执行大量方法,导致栈空间耗尽;

    3、方法内声明了海量的局部变量;

    4、 数组、List、map数据是否过大;

    更多相关内容
  • MSP430 数组填充越界引起的栈溢出 导致程序跑飞。
  • 基本的栈溢出攻击,是最早产生的一种缓冲区溢出攻击方法,它是所有其他缓冲区溢出攻击的基础。但是,由于这种攻击方法产生的时间比较长,故而GCC编译器、Linux操作系统提供了一些机制来阻止这种攻击方法对系统产生...
  • 栈溢出crash小合集

    2018-11-15 10:06:18
    自己收集的一些栈溢出可执行程序,自己通过AFL fuzz出大量的crash,是做漏洞挖掘实验验证所需的。
  • [内存溢出]栈溢出基础版

    千次阅读 2020-12-22 04:45:00
    一、进程使用的内存都可以按照功能大致分为以下4个部分:代码区、数据区、堆区、栈区______________________________________________________________________二、栈溢出ESP: 系统栈最上面一个栈帧的栈顶EBP:系统...

    一、进程使用的内存都可以按照功能大致分为以下4个部分:

    代码区、数据区、堆区、栈区

    ______________________________________________________________________

    二、栈溢出

    ESP: 系统栈最上面一个栈帧的栈顶

    EBP:系统栈最上面一个栈帧的底部

    EIP: 指向下一条等待执行的指令地址

    在函数栈帧中,一般包含以下几类重要信息:

    局部变量:为函数局部变量开辟的内存空间

    栈帧状态值:保存前栈帧的顶部和底部(实际只保存底部,顶部通过堆栈平衡得到)

    函数返回地址:保存当前函数调用前的“断点”

    函数调用步骤:

    参数入栈:从左到右

    返回地址入栈:将代码区调用指令的下一条指令地址压入栈中

    代码区跳转:从当前代码区跳转到被调用函数的入口

    栈帧调整:保存当前栈帧状态,以备后面恢复本栈帧时使用(EBP入栈)-> 把当前栈帧切换到新栈帧(ESP装入EBP)-> 给新栈帧分配空间(ESP减去所需空间大小,抬高栈顶)

    push arg3;

    push arg2;

    push arg1;

    call 函数地址;(1.保存返回地址    2.jmp 入口地址;)

    push ebp;

    mov ebp esp;

    sub esp xxx;

    函数返回步骤:

    保存返回值:通常将函数的返回值保存在EAX中

    弹出当前栈,恢复上一栈帧。具体包括:在堆栈平衡的基础上,给ESP加上栈帧的大小,降低栈顶,回收当前栈帧的空间;将当前栈帧底部保存的前栈帧EBP值弹入EBP寄存器,恢复上一个栈帧;将函数的返回地址弹给EIP寄存器;

    pop ebp;将上一栈帧底部恢复到EBP;

    retn;(1.弹出栈顶,即返回地址;   2.处理器跳转到返回地址)

    修改邻接变量的原理

    函数的局部变量在栈中一个挨着一个排列,如果这些局部变量中有数组之类的缓冲区,并且程序中存在数组越界的缺陷,那么越界的数组元素就有可能破坏栈中相邻变量的值,甚至破坏栈中所保存的EBP、返回地址等重要数据。(注意:数组地址增长方式:头在低地址,尾在高地址)

    “内存数据”中的DWORD和我们逻辑上使用的“数值数据”是按照字节逆序过的

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

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

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

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

    三)是否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性能更好。

    public class Test {

    public void testHeap(){  
        for(;;){  //死循环一直创建对象,堆溢出
              ArrayList list = new ArrayList (2000);  
          }  
    }  
    int num=1;  
    public void testStack(){  //无出口的递归调用,栈溢出
        num++;  
        this.testStack();  
     }  
      
    public static void main(String[] args){  
        Test  t  = new Test ();  
        t.testHeap();  
        t.testStack();     
    }  
    

    }
    2、栈溢出的原因
    一)、是否有递归调用

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

    三)、全局变量是否过多

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

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

    后续持续更新 请看到的及时补充到评论区……

    下面是摘自掘金中的一篇文章,在项目过程中或多或少遇到过,由于本人不想再一一做测试用例,就摘录过来了,最后附带地址链接 ,可以方便大家去看原文(尊重原著)

    JVM系列之实战内存溢出异常
    实战内存溢出异常
    大家好,相信大部分Javaer在code时经常会遇到本地代码运行正常,但在生产环境偶尔会莫名其妙的报一些关于内存的异常,StackOverFlowError,OutOfMemoryError异常是最常见的。今天就基于上篇文章JVM系列之Java内存结构详解讲解的各个内存区域重点实战分析下内存溢出的情况。在此之前,我还是想多余累赘一些其他关于对象的问题,具体内容如下:

    文章结构

    对象的创建过程
    对象的内存布局
    对象的访问定位
    实战内存异常
    1 . 对象的创建过程
    关于对象的创建,第一反应是new关键字,那么本文就主要讲解new关键字创建对象的过程。

    Student stu =new Student(“张三”,“18”);
    就拿上面这句代码来说,虚拟机首先会去检查Student这个类有没有被加载,如果没有,首先去加载这个类到方法区,然后根据加载的Class类对象创建stu实例对象,需要注意的是,stu对象所需的内存大小在Student类加载完成后便可完全确定。内存分配完成后,虚拟机需要将分配到的内存空间的实例数据部分初始化为零值,这也就是为什么我们在编写Java代码时创建一个变量不需要初始化。紧接着,虚拟机会对对象的对象头进行必要的设置,如这个对象属于哪个类,如何找到类的元数据(Class对象),对象的锁信息,GC分代年龄等。设置完对象头信息后,调用类的构造函数。
    其实讲实话,虚拟机创建对象的过程远不止这么简单,我这里只是把大致的脉络讲解了一下,方便大家理解。

    2 . 对象的内存布局
    刚刚提到的实例数据,对象头,有些小伙伴也许有点陌生,这一小节就详细讲解一下对象的内存布局,对象创建完成后大致可以分为以下几个部分:

    对象头
    实例数据
    对齐填充
    对象头: 对象头中包含了对象运行时一些必要的信息,如GC分代信息,锁信息,哈希码,指向Class类元信息的指针等,其中对Javaer比较有用的是锁信息与指向Class对象的指针,关于锁信息,后期有机会讲解并发编程JUC时再扩展,关于指向Class对象的指针其实很好理解。比如上面那个Student的例子,当我们拿到stu对象时,调用Class stuClass=stu.getClass();的时候,其实就是根据这个指针去拿到了stu对象所属的Student类在方法区存放的Class类对象。虽然说的有点拗口,但这句话我反复琢磨了好几遍,应该是说清楚了。_

    实例数据:实例数据部分是对象真正存储的有效信息,就是程序代码中所定义的各种类型的字段内容。

    对齐填充:虚拟机规范要求对象大小必须是8字节的整数倍。对齐填充其实就是来补全对象大小的。

    3 . 对象的访问定位
    谈到对象的访问,还拿上面学生的例子来说,当我们拿到stu对象时,直接调用stu.getName();时,其实就完成了对对象的访问。但这里要累赘说一下的是,stu虽然通常被认为是一个对象,其实准确来说是不准确的,stu只是一个变量,变量里存储的是指向对象的指针,(如果干过C或者C++的小伙伴应该比较清楚指针这个概念),当我们调用stu.getName()时,虚拟机会根据指针找到堆里面的对象然后拿到实例数据name.需要注意的是,当我们调用stu.getClass()时,虚拟机会首先根据stu指针定位到堆里面的对象,然后根据对象头里面存储的指向Class类元信息的指针再次到方法区拿到Class对象,进行了两次指针寻找。具体讲解图如下:

    4 .实战内存异常
    内存异常是我们工作当中经常会遇到问题,但如果仅仅会通过加大内存参数来解决问题显然是不够的,应该通过一定的手段定位问题,到底是因为参数问题,还是程序问题(无限创建,内存泄露)。定位问题后才能采取合适的解决方案,而不是一内存溢出就查找相关参数加大。

    概念

    内存泄露:代码中的某个对象本应该被虚拟机回收,但因为拥有GCRoot引用而没有被回收。关于GCRoot概念,下一篇文章讲解。
    内存溢出: 虚拟机由于堆中拥有太多不可回收对象没有回收,导致无法继续创建新对象。
    在分析问题之前先给大家讲一讲排查内存溢出问题的方法,内存溢出时JVM虚拟机会退出,那么我们怎么知道JVM运行时的各种信息呢,Dump机制会帮助我们,可以通过加上VM参数-XX:+HeapDumpOnOutOfMemoryError让虚拟机在出现内存溢出异常时生成dump文件,然后通过外部工具(作者使用的是VisualVM)来具体分析异常的原因。

    下面从以下几个方面来配合代码实战演示内存溢出及如何定位:

    Java堆内存异常
    Java栈内存异常
    方法区内存异常
    Java堆内存异常
    /** VM Args: //这两个参数保证了堆中的可分配内存固定为20M -Xms20m -Xmx20m //文件生成的位置,作则生成在桌面的一个目录 -XX:+HeapDumpOnOutOfMemoryError //文件生成的位置,作则生成在桌面的一个目录 //文件生成的位置,作则生成在桌面的一个目录 -XX:HeapDumpPath=/Users/zdy/Desktop/dump/ */
    public class HeapOOM {
    //创建一个内部类用于创建对象使用
    static class OOMObject {
    }
    public static void main(String[] args) {
    List list = new ArrayList();
    //无限创建对象,在堆中
    while (true) {
    list.add(new OOMObject());
    }
    }
    }
    Run起来代码后爆出异常如下:

    java.lang.OutOfMemoryError: Java heap space
    Dumping heap to /Users/zdy/Desktop/dump/java_pid1099.hprof …

    可以看到生成了dump文件到指定目录。并且爆出了OutOfMemoryError,还告诉了你是哪一片区域出的问题:heap space

    打开VisualVM工具导入对应的heapDump文件(如何使用请读者自行查阅相关资料),相应的说明见图:

    “类标签”

    “类标签”

    切换到"实例数"标签页
    “实例数标签”

    “实例数标签”

    分析dump文件后,我们可以知道,OOMObject这个类创建了810326个实例。所以它能不溢出吗?接下来就在代码里找这个类在哪new的。排查问题。(我们的样例代码就不用排查了,While循环太凶猛了)

    Java栈内存异常
    老实说,在栈中出现异常(StackOverFlowError)的概率小到和去苹果专卖店买手机,买回来后发现是Android系统的概率是一样的。因为作者确实没有在生产环境中遇到过,除了自己作死写样例代码测试。先说一下异常出现的情况,前面讲到过,方法调用的过程就是方法帧进虚拟机栈和出虚拟机栈的过程,那么有两种情况可以导致StackOverFlowError,当一个方法帧(比如需要2M内存)进入到虚拟机栈(比如还剩下1M内存)的时候,就会报出StackOverFlow.这里先说一个概念,栈深度:指目前虚拟机栈中没有出栈的方法帧。虚拟机栈容量通过参数-Xss来控制,下面通过一段代码,把栈容量人为的调小一点,然后通过递归调用触发异常。

    /** * VM Args: //设置栈容量为160K,默认1M -Xss160k */
    public class JavaVMStackSOF {
    private int stackLength = 1;
    public void stackLeak() {
    stackLength++;
    //递归调用,触发异常
    stackLeak();
    }

    public static void main(String[] args) throws Throwable {
        JavaVMStackSOF oom = new JavaVMStackSOF();
        try {
            oom.stackLeak();
        } catch (Throwable e) {
            System.out.println("stack length:" + oom.stackLength);
            throw e;
        }
    }
    

    }
    结果如下:
    stack length:751
    Exception in thread “main” java.lang.StackOverflowError

    可以看到,递归调用了751次,栈容量不够用了。
    默认的栈容量在正常的方法调用时,栈深度可以达到1000-2000深度,所以,一般的递归是可以承受的住的。如果你的代码出现了StackOverflowError,首先检查代码,而不是改参数。

    这里顺带提一下,很多人在做多线程开发时,当创建很多线程时,容易出现OOM(OutOfMemoryError),这时可以通过具体情况,减少最大堆容量,或者栈容量来解决问题,这是为什么呢。请看下面的公式:

    线程数*(最大栈容量)+最大堆值+其他内存(忽略不计或者一般不改动)=机器最大内存

    当线程数比较多时,且无法通过业务上削减线程数,那么再不换机器的情况下,你只能把最大栈容量设置小一点,或者把最大堆值设置小一点。

    方法区内存异常
    写到这里时,作者本来想写一个无限创建动态代理对象的例子来演示方法区溢出,避开谈论JDK7与JDK8的内存区域变更的过渡,但细想一想,还是把这一块从始致终的说清楚。在上一篇文章中JVM系列之Java内存结构详解讲到方法区时提到,JDK7环境下方法区包括了(运行时常量池),其实这么说是不准确的。因为从JDK7开始,HotSpot团队就想到开始去"永久代",大家首先明确一个概念,方法区和"永久代"(PermGen space)是两个概念,方法区是JVM虚拟机规范,任何虚拟机实现(J9等)都不能少这个区间,而"永久代"只是HotSpot对方法区的一个实现。为了把知识点列清楚,我还是才用列表的形式:

    JDK7之前(包括JDK7)拥有"永久代"(PermGen space),用来实现方法区。但在JDK7中已经逐渐在实现中把永久代中把很多东西移了出来,比如:符号引用(Symbols)转移到了native heap,运行时常量池(interned strings)转移到了java heap;类的静态变量(class statics)转移到了java heap.
    所以这就是为什么我说上一篇文章中说方法区中包含运行时常量池是不正确的,因为已经移动到了java heap;
    在JDK7之前(包括7)可以通过-XX:PermSize -XX:MaxPermSize来控制永久代的大小.
    JDK8正式去除"永久代",换成Metaspace(元空间)作为JVM虚拟机规范中方法区的实现。
    元空间与永久代之间最大的区别在于:元空间并不在虚拟机中,而是使用本地内存。因此,默认情况下,元空间的大小仅受本地内存限制,但仍可以通过参数控制:-XX:MetaspaceSize与-XX:MaxMetaspaceSize来控制大小。
    下面作者还是通过一段代码,来不停的创建Class对象,在JDK8中可以看到metaSpace内存溢出:

    /** 作者准备在JDK8下测试方法区,所以设置了Metaspace的大小为固定的8M -XX:MetaspaceSize=8m -XX:MaxMetaspaceSize=8m */
    public class JavaMethodAreaOOM {

    public static void main(String[] args) {
        while (true) {
            Enhancer enhancer = new Enhancer();
            enhancer.setSuperclass(OOMObject.class);
            enhancer.setUseCache(false);
            enhancer.setCallback(new MethodInterceptor() {
                public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
                    return proxy.invokeSuper(obj, args);
                }
            });
            //无限创建动态代理,生成Class对象
            enhancer.create();
        }
    }
    
    static class OOMObject {
    
    }
    

    }
    在JDK8的环境下将报出异常:
    Exception in thread “main” java.lang.OutOfMemoryError: Metaspace
    这是因为在调用CGLib的创建代理时会生成动态代理类,即Class对象到Metaspace,所以While一下就出异常了。
    提醒一下:虽然我们日常叫"堆Dump",但是dump技术不仅仅是对于"堆"区域才有效,而是针对OOM的,也就是说不管什么区域,凡是能够报出OOM错误的,都可以使用dump技术生成dump文件来分析。

    在经常动态生成大量Class的应用中,需要特别注意类的回收状况,这类场景除了例子中的CGLib技术,常见的还有,大量JSP,反射,OSGI等。需要特别注意,当出现此类异常,应该知道是哪里出了问题,然后看是调整参数,还是在代码层面优化。

    附加-直接内存异常
    直接内存异常非常少见,而且机制很特殊,因为直接内存不是直接向操作系统分配内存,而且通过计算得到的内存不够而手动抛出异常,所以当你发现你的dump文件很小,而且没有明显异常,只是告诉你OOM,你就可以考虑下你代码里面是不是直接或者间接使用了NIO而导致直接内存溢出。

    展开全文
  • 出处1:http://www.iteye.com写java程序时大家一定对一下两条异常并不陌生: java.lang.OutOfMemoryError: Java heap space java.lang.OutOfMemoryError: Perm... 好的编码实践可能会大大降低内存溢出的产生。 ...

    出处1:http://www.iteye.com

    写java程序时大家一定对一下两条异常并不陌生: 

    java.lang.OutOfMemoryError: Java heap space 
    java.lang.OutOfMemoryError: PermGen space 
    尤其当应用服务器(Java容器)出现上述情况更是让人有一种天塌下来的感觉。 

       好的编码实践可能会大大降低内存溢出的产生。 
       本文并不是写如何规避内存溢出,但是我还是要介绍一下如何能够尽量规避内存溢出: 
       1. 编码规范认真执行。找几个资深程序猿(或者整个项目组讨论后)写一个Java编码规范,让项目组成员尽量遵守。一目了然的代码更容易定位问题,当然也更能让人写出好的代码。 
       2. 单元测试要覆盖所有分支与边界条件。不要拿某种情况不会出现做借口。有句老话说常在河边站哪有不湿鞋(学名墨菲定律)。 
       3. 代码审查要走。代码写完了,找资深程序猿扫扫代码没有坏处。 
       4. 有条件的项目组要充分利用测试人员的能动性。 
       5. 如果项目的期望较高,就把上面的尽量、可能等词汇改成一定要。 

       以上五条建议对非性命攸关型项目足够了。 


    下面说正题: 


       对于java.lang.OutOfMemoryError: PermGen space 这种情况更多的是靠程序猿的经验来解决: 

       PermGen space的全称是Permanent Generation space,是指内存的永久保存区域, 这块内存主要是被JVM存放Class和Meta信息的,Class在被Load时就会被放到PermGen space中, 它和存放类实例(Instance)的Heap区域不同,GC(Garbage Collection)不会在主程序运行期对 PermGen space进行清理,所以如果你的应用中有很多CLASS的话,就很可能出现PermGen space错误。 

       通过上面的描述就可以得出:如果要加载的class与jar文件大小超过-XX:MaxPermSize就有可能会产生java.lang.OutOfMemoryError: PermGen space 。 

       换句话说-XX:MaxPermSize的大小要超过class与jar的大小。通常-XX:MaxPermSize为-Xmx的1/8。 
       
       对于java.lang.OutOfMemoryError: Java heap space 可能定位的过程就需要折腾一翻了:

       虽然各种java虚拟机的实现机制不一,但是heap space内存溢出产生的原因相同:那就是堆内存不够虚拟机分配了。 

       我对java虚拟机的实现不感兴趣,对各种虚拟机的内存分配机制与gc的交互关系也不了解。但是我大致认为内存分配机制与gc是有联系的,也就是说内存不够分配时gc肯定也释放不了堆内存。从这一点出发,我们就需要找为什么gc释放不了堆内存。通常来说释放不了是因为内存还在使用。对于java对象产生的堆内存占用,只要其不再被继续引用gc是能够顺利回收的(对于通过本地方法调用,即JNI调用产生内存泄露的情况暂不考虑)。 

       问题的关键就找到了,当产生heap space内存溢出时,堆内存中对象数量过多的就可能是问题的根源了。例外的情况是,程序确实需要那么多内存,这时就要考虑增大堆内存。 

       例外的情况在本文中就不再多说了,下面介绍jdk自带的两个可视化工具来定位问题。 

    jdk/jconsole.exe  jdk/jvisualvm.exe 
       
       jconsole.exe可以查看本地以及远程主机上的java虚拟机的当前状况,这对服务器健康检查情况非常有用。如下图: 
     

       jvisualvm.exe可以用来查看分析内存转储文件;也可以用其做java虚拟机当前状况查看,但是jvisualvm.exe的侵入性非常强,一旦使用会严重影响应用性能。如下图: 

     

      下面写些代码来演示一下内存溢出的产生,堆转储文件的生成,堆内存的分析。 
      
      首先创建数据持有对象类: 

    package com.zas.jvm.om;
    
    /**
     * 数据对象
     * @author zas
     */
    public class DataObject {
    	//数据对象ID
    	private String id;
    	//数据对象内容
    	private String des;
    	
    	public DataObject(String id, String des) {
    		super();
    		this.id = id;
    		this.des = des;
    	}
    
    	public String getId() {
    		return id;
    	}
    
    	public void setId(String id) {
    		this.id = id;
    	}
    
    	public String getDes() {
    		return des;
    	}
    
    	public void setDes(String des) {
    		this.des = des;
    	}
    
    	@Override
    	public String toString() {
    		return "DataObject [id=" + id + ", des=" + des + "]";
    	}
    	/**
    	 * @param args
    	 */
    	public static void main(String[] args) {
    
    	}
    
    }
    


    溢出演示代码 
    package com.zas.jvm.om;
    
    import java.util.ArrayList;
    import java.util.List;
    
    public class OutMemeryTest {
    	
    	List<DataObject> list = new ArrayList<DataObject>();
    	
    	public void testOm(){
    		for (int i = 0; i < 100000; i++) {
    			DataObject data = new DataObject("id&"+i, "des:"+i);
    			list.add(data);
    		}
    	}
    	/**
    	 * @param args
    	 */
    	public static void main(String[] args) {
    		OutMemeryTest omt = new OutMemeryTest();
    		for (int i = 0; i < 2; i++) {
    			omt.testOm();
    		}
    		System.out.println("DOne!");
    		try {
    			Thread.sleep(100000000);
    		} catch (InterruptedException e) {
    			e.printStackTrace();
    		}
    	}
    
    }
    



    运行参数设置如下:-Xms64m -Xmx64m -XX:PermSize=8m -XX:MaxPermSize=8m 
    -XX:-HeapDumpOnOutOfMemoryError           
    见下图: 

     


    jvisualvm分析效果图: 
        

    从上图结合代码明显得出:com.zas.jvm.om.DataObject这个类的对象出了问题。 


    以上是一个演示问题产生及定位过程,生产环境的问题千奇百怪需要具体问题具体分析。 

    当堆内存巨大时可能要调整jdk\lib\visualvm\etc\visualvm.conf文件中的-xms -xmx大小来导入转储文件。 

    生产环境为linux的较多,可以借助jdk自带的jmap来转储堆内存文件来分析。

    -------------------------------------------------------------------------------------------------------------------------------------------------------------

    java 内存溢出 栈溢出的原因与排查方法

     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工具进行查找大概出现栈溢出的位置


    展开全文
  • 堆溢出与栈溢出原因分析

    万次阅读 2017-06-02 16:06:15
    堆溢出:不断的new 一个对象,一直创建新的对象,栈溢出:死循环或者是递归太深,递归的原因,可能太大,也可能没有终止。 在一次函数调用中,栈中将被依次压入:参数,返回地址,EBP。如果函数有局部变量,接下来,...
  • 浅析栈溢出原理

    千次阅读 2020-10-20 20:55:49
    造成栈溢出原因 系统栈是由高地址往低地址增长的, 而数据的写入是按低地址到高地址的顺序写入. 如果程序没有对输入的字符数量做出限制, 就存在数据溢出当前栈帧以及覆盖返回地址的可能,从而实现控制程序的执行流....
  • V5-305_FreeRTOS实验_任务栈溢出检测方式一 (模拟栈溢出
  • 递归调用中栈溢出原因

    千次阅读 2016-09-17 11:17:35
    那么过多的递归调用为什么会引起栈溢出呢?事实上,函数调用的参数是通过栈空间来传递的,在调用过程中会占用线程的栈资源。而递归调用,只有走到最后的结束点后函数才能依次退出,而未到达最后的结束点之前,占用的...
  • 1、 内存溢出原因是什么? 内存溢出是由于没被引用的对象(垃圾)过多造成JVM没有及时回收,造成的内存溢出。如果出现这种现象可行代码排查: 一)是否App中的类中和引用变量过多使用了Static修饰 如public staitc...
  • 栈溢出原因

    千次阅读 2016-04-07 12:15:31
    堆和栈都有各自的大小,栈溢出指的是栈的使用超出了栈的大小,一个原因有两个: 1、 局部数组变量空间太大  局部变量是存储在栈中的,因此这个很好理解  解决这类问题的办法有两个,  一是增大栈空间,二...
  • 栈溢出攻击技术

    2018-03-13 15:16:13
    缓冲区溢出攻击技术-栈溢出攻击技术。网络安全相关。
  • 经典栈溢出PPT

    2018-11-28 21:04:23
    比较简洁的栈溢出的PPT,适合新手入门使用的教程,作用相当于一篇较简短的博客!
  • java内存溢出 原因与排查方法 1、 内存溢出原因是什么? 内存溢出是由于没被引用的对象(垃圾)过多造成JVM没有及时回收,导致剩余的内存不够用,造成的内存溢出。如果出现这种现象可行代码排查: 一)是否应用...
  • 栈溢出基础

    2021-01-17 16:14:06
    基础知识什么是缓冲区溢出在深入探讨技术之前, 让我们先了解一下缓冲区溢出的实际内容.想象一个非常简单的程序, 要求你输入你的用户名, 然后返回到它在做什么.从视觉上看, 如下所示注意到括号之间的空格是输入...
  • 64位Linux下的栈溢出

    2014-10-05 11:43:55
    0x01 x86和x86_64的区别 0x02 漏洞代码片段 0x03 触发溢出 0x04 控制RIP 0x05 跳入用户控制的缓冲区 0x06 执行shellcode 0x07 GDB vs 现实 0x08 结语
  • V5-306_FreeRTOS实验_任务栈溢出检测方式二 (模拟栈溢出
  • linux栈溢出

    千次阅读 2022-02-01 20:57:06
    基础知识 结构 函数调用过程 32位为例: KaTeX parse error: No such environment: align* at position 8: \begin{̲a̲l̲i̲g̲n̲*̲}̲ & \text{push a… 函数参数传递 32位程序 普通函数传参:参数...
  • 栈溢出原理

    千次阅读 2021-08-06 23:31:31
    文章目录栈溢出原理前言:栈一、栈溢出原理二、栈保护技术三、常发生栈溢出的危险函数四、可利用的栈溢出覆盖位置总结 前言:栈 栈是一种LIFO的数据结构。 应用程序有一到多个用户态栈。 栈自底向上增长,由指令...
  • 计算机程序一般都会使用到一些内存,这些内存会提供给程序内部使用,或者是存放用户的输入数据,这样的内存一般称作缓冲区。...只不过栈溢出发生在栈上,而堆溢出发生在堆上,其实他们的原理都是一样的。
  • 怎样解决栈溢出

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

    千次阅读 2021-05-28 11:31:14
    在我们平时开发的过程中,经常会出现stack overflow的情况导致程序崩溃,通常的原因都是无限的递归调用导致的,也就是无限的调用函数,导致空间用完,可是为什么非要使用呢,它内部是怎么运行的,的空间一共有多...
  • 栈溢出和堆溢出

    千次阅读 2021-06-07 21:19:59
    1. 栈溢出StackOverflowError 栈是线程私有的,生命周期与线程相同,每个方法在执行的时候都会创建一个栈帧,用来存储局部变量表,操作数栈,动态链接,方法出口等信息。 栈溢出:方法执行时创建的栈帧个数超过了栈...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 164,409
精华内容 65,763
关键字:

栈溢出的原因