Java堆栈溢出的机制与原理

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java堆栈溢出的机制与原理相关的知识,希望对你有一定的参考价值。

参考技术A

  Java堆栈溢出的出现 很让人痛苦的事情 很多时候都无法找到头绪 这里作者通过使用jrockit调用程序才最终发现了问题的所在 在很多情况下 Java堆栈溢出 很有可能是你的代码中用到数组 到你的索引超出范围了

  java lang OutOfMemoryError: Java heap space

  在Java程序运行中可能会报如上的错误 通常是在运行过程中内存占用了没有别释放造成的

  以前可能没法跟踪可能是很痛苦的事情 现在好了 我们有一个调试软件可以用了 在生产环境下使用的jRockit软件进行调试 是Oracle公司出品的

  前两天试用了一下真的很不错

  前阵子有个程序跑 个礼拜左右就会出现Java堆栈溢出 始终找不到头绪 后来使用jrockit才找到问题的出处

  jrockit是可以调试远程程序也可以调试本地程序的

  具体调试步骤

   (一)

  如果是调试本地程序的话 启动jrockit 然后启动本地需要调试的程序 会在左侧工具栏 本地目录下创建一个连接为需要调试的程序 在上面点击右键 就会启动跟踪

  如何跟踪呢 我的办法就是等 在跟踪开始后 进行截图 然后等程序运行一段时间后查找堆增长比较大的并且一直没有释放的变量

  (二)

  然后在上面点击右键 显示分配跟踪

  (三)

  然后找到对应的方法 然后就去找问题吧 看看是不是那个地方有内存一直没有释放啊

  然后说点我自己的小经验 也许是不对的 但是我在我的应用里面确实是有效的

  在经常需要调用的地方将变量设成全局的甚至是静态的 我的操作是设成全局的了 图省事呢 呵呵 因为我的变量时全局都要调用的而且是频繁调用的

  用完的变量一定要记得让它等于null 否则执行gc()貌似是不给回收的

  基本上jrockit跟踪是很强的 都能够找到你的问题所在 要仔细观察 改完程序后记得再重新跟踪下直到没有内存泄露为止

  写完手工

lishixinzhi/Article/program/Java/hx/201311/26094

前端知识体系:JavaScript基础-作用域和闭包-闭包的实现原理和作用以及堆栈溢出和内存泄漏原理和相应解决办法

闭包的实现原理和作用

闭包:

有权访问另一个函数作用域中的变量的函数。

创建闭包的常见方式就是,在一个函数中创建另一个函数。

闭包的作用:

访问函数内部变量、保持函数在环境中一直存在,不会被垃圾回收机制处理

因为函数内部声明 的变量是局部的,只能在函数内部访问到,但是函数外部的变量是对函数内部可见的,这就是作用域链的特点了。

子级可以向父级查找变量,逐级查找,找到为止

因此我们可以在函数内部再创建一个函数,这样对内部的函数来说,外层函数的变量都是可见的,然后我们就可以访问到他的变量了。

<script>
    function  bar(){
        //外层函数声明的变量
        var value=1;
        function foo(){
            console.log(value);
        }
        return foo();
    };
    var bar2=bar;
    //实际上bar()函数并没有因为执行完就被垃圾回收机制处理掉
    //这就是闭包的作用,调用bar()函数,就会执行里面的foo函数,foo这时就会访问到外层的变量
    bar2();
</script>

foo()是包含bar()内部作用域的闭包,使得该作用域能够一直存活,不会被垃圾回收机制处理掉,这就是闭包的作用,以供foo()在任何时间进行引用。

闭包的优点:

  • 方便调用上下文中声明的局部变量
  • 逻辑紧密,可以在一个函数中再创建个函数,避免了传参的问题

闭包的缺点:

因为使用闭包,可以使函数在执行完后不被销毁,保留在内存中,如果大量使用闭包就会造成内存泄露,内存消耗很大

总结:

闭包能够访问外部函数的变量,即使变量已经离开它所创建的环境,是因为外部变量会被闭包的作用域对象所持有。闭包这种特性实现了嵌套函数之间数据的隐式传递。

闭包应用:

function addFn(a,b){
    return(function(){
        console.log(a+"+"+b);
    })
}
var test =addFn(a,b);
setTimeout(test,3000);

一般setTimeout的第一个参数是个函数,但是不能传值。如果想传值进去,可以调用一个函数返回一个内部函数的调用,将内部函数的调用传给setTimeout。内部函数执行所需的参数,外部函数传给他,在setTimeout函数中也可以访问到外部函数。

堆栈溢出和内存泄漏原理:

1、内存泄露:是指申请的内存执行完后没有及时的清理或者销毁,占用空闲内存,内存泄露过多的话,就会导致后面的程序申请不到内存。因此内存泄露会导致内部内存溢出

2、堆栈溢出:是指内存空间已经被申请完,没有足够的内存提供了

3、在一些编程软件中,比如c语言中,需要使用malloc来申请内存空间,再使用free释放掉,需要手动清除。而js中是有自己的垃圾回收机制的,一般常用的垃圾收集方法就是标记清除。

标记清除法:在一个变量进入执行环境后就给它添加一个标记:进入环境,进入环境的变量不会被释放,因为只要“执行流”进入响应的环境,就可能用到他们。当变量离开环境后,则将其标记为“离开环境”。

4、常见的内存泄露的原因:

  • 全局变量引起的内存泄露
  • 闭包
  • 没有被清除的计时器

5、解决方法:

  • 减少不必要的全局变量
  • 减少闭包的使用(因为闭包会导致内存泄露)
  • 避免死循环的发生

参考文章:

https://blog.csdn.net/alegria_x/article/details/99539024

https://www.cnblogs.com/shiyou00/p/10598010.html

https://www.jianshu.com/p/9fc2e3ee4efe

以上是关于Java堆栈溢出的机制与原理的主要内容,如果未能解决你的问题,请参考以下文章

FreeRTOS中的任务堆栈溢出检测机制

函数 堆栈溢出

内存溢出与jvm参数配置

怎么防止堆栈溢出

vb 堆栈溢出

c++堆栈溢出问题?