700字范文,内容丰富有趣,生活中的好帮手!
700字范文 > 一位面试官询问我:Java中的JVM内存溢出和内存泄露是什么?我这么回答成功拿到了offer

一位面试官询问我:Java中的JVM内存溢出和内存泄露是什么?我这么回答成功拿到了offer

时间:2020-11-03 17:51:44

相关推荐

一位面试官询问我:Java中的JVM内存溢出和内存泄露是什么?我这么回答成功拿到了offer

一位面试官询问我:Java中的JVM内存溢出和内存泄露是什么?我这么回答成功拿到了offer。

墨眉无锋墨家代码 -11-22 20:16:50 10525 收藏 56

分类专栏: Java 文章标签: java 内存泄漏 面试 jvm 编程语言

版权

一位面试官询问我:Java中的JVM内存溢出和内存泄露是什么?我这么回答成功拿到了offer。

内存泄漏(memory leak )

申请了内存用完了不释放,比如一共有 1024M 的内存,分配了 521M 的内存一直不回收,那么可以用的内存只有 521M 了,仿佛泄露掉了一部分;

通俗一点讲的话,内存泄漏就是【占着茅坑不拉shi】。

整理了最新整理收集的一线互联网公司面试真题(都整理成文档),有很多干货,包含netty,spring,线程,spring cloud等详细讲解,也有详细的学习规划图,面试题整理等,我感觉在面试这块讲的非常清楚:获取面试资料只需:点击这里领取!!!暗号:CSDN在这里插入图片描述

内存溢出(out of memory)

申请内存时,没有足够的内存可以使用;

通俗一点儿讲,一个厕所就三个坑,有两个站着茅坑不走的(内存泄漏),剩下最后一个坑,厕所表示接待压力很大,这时候一下子来了两个人,坑位(内存)就不够了,内存泄漏变成内存溢出了。

可见,内存泄漏和内存溢出的关系:内存泄露的增多,最终会导致内存溢出。

这是一个很有味道的例子。

在这里插入图片描述

如上图:

对象 X 引用对象 Y,X 的生命周期比 Y 的生命周期长;

那么当Y生命周期结束的时候,X依然引用着Y,这时候,垃圾回收期是不会回收对象Y的;

如果对象X还引用着生命周期比较短的A、B、C,对象A又引用着对象 a、b、c,这样就可能造成大量无用的对象不能被回收,进而占据了内存资源,造成内存泄漏,直到内存溢出。

泄漏的分类

经常发生:发生内存泄露的代码会被多次执行,每次执行,泄露一块内存;

偶然发生:在某些特定情况下才会发生;

一次性:发生内存泄露的方法只会执行一次;

隐式泄露:一直占着内存不释放,直到执行结束;严格的说这个不算内存泄露,因为最终释放掉了,但是如果执行时间特别长,也可能会导致内存耗尽。

导致内存泄漏的常见原因

循环过多或死循环,产生大量对象;

静态集合类引起内存泄漏,因为静态集合的生命周期和 JVM 一致,所以静态集合引用的对象不能被释放;下面这个例子中,list 是静态的,只要 JVM 不停,那么 obj 也一直不会释放。

public class OOM {

static List list = new ArrayList();

public void oomTests(){

Object obj = new Object();

list.add(obj);

}

}

1

2

3

4

5

6

7

8

9

单例模式,和静态集合导致内存泄露的原因类似,因为单例的静态特性,它的生命周期和 JVM 的生命周期一样长,所以如果单例对象如果持有外部对象的引用,那么这个外部对象也不会被回收,那么就会造成内存泄漏。

数据连接、IO、Socket连接等等,它们必须显示释放(用代码 close 掉),否则不会被 GC 回收。

try {

Connection conn = null;

Class.forName(“com.mysql.jdbc.Driver”);

conn = DriverManager.getConnection(“url”,"", “”);

Statement stmt = conn.createStatement() ;

ResultSet rs = stmt.executeQuery("…") ;

} catch (Exception e) {

//异常日志

} finally {

//1.关闭结果集 Statement

//2.关闭声明的对象 ResultSet

//3.关闭连接 Connection

}

1

2

3

4

5

6

7

8

9

10

11

12

13

内部类的对象被长期持有,那么内部类对象所属的外部类对象也不会被回收。

Hash 值发生改变,比如下面中的这个类,它的 hashCode 会随着变量 x 的变化而变化:

public class ChangeHashCode {

private int x ;

@Override

public int hashCode() {

final int prime = 31;

int result = 1;

result = prime * result + x;

return result;

}

@Override

public boolean equals(Object obj) {

if (this == obj)

return true;

if (obj == null)

return false;

if (getClass() != obj.getClass())

return false;

ChangeHashCode other = (ChangeHashCode) obj;

if (x != other.x)

return false;

return true;

}

//省略 set 、get 方法

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

public class HashSetTests {

public static void main(String[] args){

HashSet hs = new HashSet();

ChangeHashCode cc = new ChangeHashCode();

cc.setX(10);//hashCode = 41

hs.add(cc);

cc.setX(20);//hashCode = 51

System.out.println("hs.remove = " + hs.remove(cc));//false

hs.add(cc);

System.out.println("hs.size = " + hs.size());//size = 2

}

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

可以看到,在测试方法中,当元素的 hashCode 发生改变之后,就再也找不到改变之前的那个元素了;

这也是 String 为什么被设置成了不可变类型,我们可以放心地把 String 存入 HashSet,或者把 String 当做 HashMap 的 key 值;

当我们想把自己定义的类保存到散列表的时候,需要保证对象的 hashCode 不可变。

内存中加载数据量过大;之前项目在一次上线的时候,应用启动奇慢直到夯死,就是因为代码中会加载一个表中的数据到缓存(内存)中,测试环境只有几百条数据,但是生产环境有几百万的数据。

最后

最新整理收集的一线互联网公司面试真题(都整理成文档),有很多干货,包含netty,spring,线程,spring cloud等详细讲解,也有详细的学习规划图,面试题整理等,我感觉在面试这块讲的非常清楚:获取面试资料只需:点击这里领取!!!暗号:CSDN在这里插入图片描述

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。