美文网首页互联网科技java高级开发群Spring-Boot
纳尼,Java 存在内存泄泄泄泄泄泄漏吗?

纳尼,Java 存在内存泄泄泄泄泄泄漏吗?

作者: Java技术剑 | 来源:发表于2019-05-23 14:19 被阅读11次

01. 怎么回事?

纳尼,Java 不是自动管理内存吗?怎么可能会出现内存泄泄泄泄泄泄漏!

Java 最牛逼的一个特性就是垃圾回收机制,不用像 C++ 需要手动管理内存,所以作为 Java 程序员很幸福,只管 New New New 即可,反正 Java 会自动回收过期的对象。。。

那么 Java 都自动管理内存了,那怎么会出现内存泄漏,难道 Jvm 有 bug? 不要急,且听我慢慢道来。。

02. 怎么判断可以被回收

先了解一下 Jvm 是怎么判断一个对象可以被回收。一般有两种方式,一种是引用计数法,一种是可达性分析。

引用计数法:每个对象有一个引用计数属性,新增一个引用时计数加1,引用释放时计数减1,计数为0时可以回收。

这个办法看起来挺简单的,但是如果出现 A 引用了 B,B 又引用了 A,这时候就算他们都不再使用了,但因为相互引用 计算器=1 永远无法被回收。

此方法简单,无法解决对象相互循环引用的问题。

可达性分析(Reachability Analysis):从 GC Roots 开始向下搜索,搜索所走过的路径称为引用链。当一个对象到 GC Roots 没有任何引用链相连时,则证明此对象是不可用的,那么虚拟机就判断是可回收对象。

可达性分析可以解决循环引用的问题。

那么 gc roots 对象是哪些呢

        ·     虚拟机栈中引用的对象

        ·     方法区中类静态属性引用的对象

        ·     方法区中常量引用的对象

        ·     本地方法栈中JNI[即一般说的Native]引用的对象

目前主流的虚拟机中大多使用可达性分析的方式来判定对象是否可被 GC 回收。

03.什么情况下会出现内存泄漏

既然可达性分析好像已经很牛逼的样子了,怎么可能还会出现内存泄漏呢,那我们再来看一下内存泄漏的定义。

内存泄露就是指一个不再被程序使用的对象或变量一直被占据在内存中。

有可能此对象已经不使用了,但是还有其它对象保持着此对象的引用,就会导致 GC  不能回收此对象,这种情况下就会出现内存泄漏。

写一个程序让出现内存泄漏

①长生命周期的对象持有短生命周期对象的引用就很可能发生内存泄露,尽管短生命周期对象已经不再需要,但是因为长生命周期对象持有它的引用而导致不能被回收。

public class Simple {

Object object;

public void method1(){

object = new Object();

//...其他代码

}

}

这里的 object 实例,其实我们期望它只作用于 method1() 方法中,且其他地方不会再用到它,但是,当method1()方法执行完成后,object 对象所分配的内存不会马上被认为是可以被释放的对象,只有在 Simple 类创建的对象被释放后才会被释放,严格的说,这就是一种内存泄露。

解决方法就是将 object 作为 method1() 方法中的局部变量。

public class Simple {

Object object;

public void method1(){

object = new Object();

//...其他代码

object = null;

}

}

当然大家有可能会想就这一个方法也不会有多大影响,但如果在某些项目中,一个方法在一分钟之内调用上万次的时候,就会出现很明显的内存泄漏现象。

②集合中的内存泄漏,比如 HashMap、ArrayList 等,这些对象经常会发生内存泄露。比如当它们被声明为静态对象时,它们的生命周期会跟应用程序的生命周期一样长,很容易造成内存不足。

下面给出了一个关于集合内存泄露的例子。

Vector v=new Vector(10);

for (int i=1;i<100; i++)

{

Object o=new Object();

v.add(o);

o=null;

}

//此时,所有的Object对象都没有被释放,因为变量v引用这些对象。

在这个例子中,我们循环申请 Object 对象,并将所申请的对象放入一个 Vector 中,如果我们仅仅释放引用本身,那么 Vector 仍然引用该对象,所以这个对象对 GC 来说是不可回收的。

因此,如果对象加入到 Vector 后,还必须从 Vector 中删除,最简单的方法就是将 Vector 对象设置为 null。

以上两种是最常见的内存泄漏案例。当然还有一些内存泄漏的例子,这里就不再一一例举了,感兴趣的同学可以在网上找找资料。

04. 内存泄漏和内存溢出

很多朋友总是搞不清楚,内存泄漏和内存溢出的区别,它俩是两个完全不同的概念, 它们之间存在一些关联。

        ·     内存溢出 out of memory,是指程序在申请内存时,没有足够的内存空间供其使用,出现 out of memory;

        ·     内存泄露 memory leak,是指程序在申请内存后,无法释放已申请的内存空间,一次内存泄露危害可以忽略,但内存泄露堆积后果很严重,无论多少内存,迟早会被占光。

所以内存泄漏可能会导致内存溢出,但内存溢出并不完全都是因为内存泄漏,也有可能使用了太多的大对象导致。

05.如何检测内存泄漏

最后一个重要的问题,就是如何检测 Java 的内存泄漏。目前,我们通常使用一些工具来检查 Java 程序的内存泄漏问题。

市场上已有几种专业检查 Java 内存泄漏的工具,它们的基本工作原理大同小异,都是通过监测 Java 程序运行时,所有对象的申请、释放等动作,将内存管理的所有信息进行统计、分析、可视化。开发人员将根据这些信息判断程序是否有内存泄漏问题。

这些工具包括 Plumbr 、Eclipse Memory Analyzer、JProbe Profiler、JVisualVM 等。

06. 最后

以上内容其实是我曾经经常面试的内容之一,通过一系列的问题考察 Java 程序员对 Jvm 的理解。

比如我通常会问面试者,Java 中存在内存泄漏吗?大部分人都会回答存在,接着我会问如果让你写一个程序让内存泄漏,你会怎么写?大部分程序员就回答不上来了。

如果面试者可以回答上面的问题,我会接着和面试者聊聊,内存泄漏和内存溢出他们之间是否存在联系 、以及在日常工作中如何避免写出内存泄漏的代码 、如果生产出现 Jvm 相关问题时,排查问题的思路和步骤等等。

分享一份面试宝典《Java核心知识点整理.pdf》“,覆盖了JVM、锁、高并发、反射、Spring原理、微服务、Zookeeper、数据库、数据结构等等”,还有Java208道面试题(含答案)加入群(Java填坑之路)789337293 即可免费获取到!

相关文章

  • 纳尼,Java 存在内存泄泄泄泄泄泄漏吗?

    01.怎么回事? 纳尼,Java 不是自动管理内存吗?怎么可能会出现内存泄泄泄泄泄泄漏! Java 最牛逼的一个特...

  • 【《泄》】

    【《泄》】 原创/简垃圾 暑眠惊雹起, 枯叶满池塘。 犹盼经年下, 寻奸灭贼王。 2018年06月27日

  • 从QQ到微信,再到微博,再到今天的简书,从同学到同事到好友,自己的圈子在一点一点的收缩,为了所谓的隐私,早已没有了...

  • 见春光遇冬雪 饱受煎熬的风 碰到了 满地的落叶 我们在一起了

  • 愚我风牛马不相及 蠢我枯木也不逢春 狂我年少壮志难酬 妄我无知却非浅薄 这世界风雷滚滚 暗无天日长风千里 我心里惊...

  • 说人没有高低贵贱,三六九等级之分都是骗人的,只不过是高不与低争,贵不与贱比,罢了。赋诗感慨一下: (泄...

  • 几天的自我安慰的复习给了我荒废时间的荒诞理由借口,一事无成。 天亮进行期末的考试,此刻难得不用荒诞填满。 尝试静一...

  • 昏昏沉沉的第二天,看见了自己的懒惰,生活的无序。这样的日子里,只能承受,来了事情就去做去,程序化无创意,了无生气...

  • 泄泄心里的毒

    觉得自己像是八音盒中跳芭蕾舞的公主,每当跳的兴致勃勃时,却随着音乐的嘎然而止,定格在盒子里,这才意识到自己仅仅是一...

  • 神农本草经 - 未完持续更新中

    五脏補泄肝:辛補酸泄心:咸補苦泄脾:甘補辛泄肺:酸補咸泄肾:苦補甘泄 * 甘: 缓心脏不好,又抽筋。甘草是苦味入心...

网友评论

    本文标题:纳尼,Java 存在内存泄泄泄泄泄泄漏吗?

    本文链接:https://www.haomeiwen.com/subject/fmwvzqtx.html