概念

内存泄露:指程序中动态分配内存给一些临时对象,但对象不会被GC回收,它始终占用内存,被分配的对象可达但已无用。即无用对象持续占有内存或无用对象的内存得不到及时释放,从而造成的内存空间浪费。

可达性分析算法

JVM使用可达性分析算法判断对象是否存活。

GC Root

通过一系列名为“GC Roots”的对象作为起点,从这些结点开始向下搜索,搜索所走过的路径称为“引用链(Reference Chain)”,当一个对象到GC Roots没有任何饮用链相连时,则证明此对象是不可用的。

object4、object5、object6虽然有互相判断,但是它们到GC Rootd是不可达的,所以它们将会判定为是可回收对象。

可以作为GC Roots的对象有:

  • 虚拟机栈(栈帧中的本地变量表)中的引用的对象;
  • 方法区中的类静态属性引用的对象;
  • 方法区中的常量引用的对象;
  • 本地方法栈中JNI的引用的对象

虽然Java有垃圾收集器帮组实现内存自动管理,虽然GC有效的处理了大部分内存,但是并不能完全保证内存的不泄漏。

内存泄漏

内存泄漏就是堆内存中不再使用的对象无法被垃圾收集器清除掉,因此它们会不必要地存在。这样就导致了内存消耗,降低了系统的性能,最终导致OOM使得进程终止。

内存泄漏的表现:

  • 应用程序长时间连续运行时性能严重下降;
  • 应用程序中的OutOfMemoryError堆错误;
  • 自发且奇怪的应用程序崩溃;
  • 应用程序偶尔会耗尽连接对象;

可能导致内存泄漏的原因:

1. static字段引起的内存泄漏

大量使用static字段会潜在的导致内存泄漏,在Java中,静态字段通常拥有与整个应用程序相匹配的生命周期。

解决办法:最大限度的减少静态变量的使用;单例模式时,依赖于延迟加载对象而不是立即加载的方式(即采用懒汉模式,而不是饿汉模式)

2. 未关闭的资源导致内存泄漏

每当创建连接或者打开流时,JVM都会为这些资源分配内存。如果没有关闭连接,会导致持续占有内存。在任意情况下,资源留下的开放连接都会消耗内存,如果不处理,就会降低性能,甚至OOM。

解决办法:使用finally块关闭资源;关闭资源的代码,不应该有异常;JDK1.7之后,可以使用太try-with-resource块。

3. 不正确的equals()和hashCode()

在HashMap和HashSet这种集合中,常常用到equal()和hashCode()来比较对象,如果重写不合理,将会成为潜在的内存泄漏问题。

解决办法:用最佳的方式重写equals()和hashCode().

4. 引用了外部类的内部类

非静态内部类的初始化,总是需要外部类的实例;默认情况下,每个非静态内部类都包含对其外部类的隐式引用,如果我们在应用程序中使用这个内部类对象,那么即使在我们的外部类对象超出范围后,它也不会被垃圾收集器清除掉。

解决办法:如果内部类不需要访问外部类包含的类成员,可以转换为静态类。

5. finalize方法导致的内存泄漏

重写finalize()方法时,该类的对象不会立即被垃圾收集器收集,如果finalize()方法的代码有问题,那么会潜在的印发OOM;

解决办法:避免重写finalize()方法。

6. 常量字符串造成的内存泄漏

如果我们读取一个很大的String对象,并调用了intern(),那么它将放到字符串池中,位于PermGen中,只要应用程序运行,该字符串就会保留,这就会占用内存,可能造成OOM。(针对JDK1.6及以前,常量池在PermGen永久代中)

解决办法:增加PermGen的大小,-XX:MaxPermSize=512M;JDK1.7以后字符串池转移到了堆中。

intern()方法详解:

String str1 = "abc";
String str2 = "abc";
String str3 = new String("abc");
String str4 = str3.intern(); System.out.println(str1 == str2);
System.out.println(str2 == str3); System.out.println(str1 == str4);
System.out.println(str3 == str4); true, false, true, false

intern()方法搜索字符串常量池,如果存在指定的字符串,就返回之;

否则,就将该字符串放入常量池并返回之。

换言之,intern()方法保证每次返回的都是 同一个字符串对象

String str1 = "abc";
String str2 = "abc";
String str3 = new String("abcd");
String str4 = str3.intern();
String str5 = "abcd"; System.out.println(str1 == str2);
System.out.println(str2 == str3); System.out.println(str1 == str4);
System.out.println(str3 == str4); System.out.println(str4 == str5); true
false
false
false
true

为何要使用intern()方法?看看equals方法的源码:

public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
if (anObject instanceof String) {
String anotherString = (String)anObject;
int n = value.length;
if (n == anotherString.value.length) {
char v1[] = value;
char v2[] = anotherString.value;
int i = 0;
while (n-- != 0) {
if (v1[i] != v2[i])
return false;
i++;
}
return true;
}
}
return false;
}

可以看到,比较两个字符串的时候,首先比较两个字符串对象是否地址相同,不同再挨个比较字符。这样就大大加快了比较的速度。否则若每次都挨个比较将是非常耗时的。

7. 使用ThreadLocal造成内存泄漏

使用ThreadLocal时,每个线程只要处于存活状态就可保留对其ThreadLocal变量副本的隐式调用,且将保留其自己的副本。使用不当,就会引起内存泄漏。

一旦线程不再存在,该线程的threadLocal对象就应该被垃圾收集,而现在线程的创建都是使用线程池,线程池有线程重用的功能,因此线程就不会被垃圾回收器回收。所以使用到ThreadLocal来保留线程池中的线程的变量副本时,ThreadLocal没有显式地删除时,就会一直保留在内存中,不会被垃圾回收。

解决办法:不再使用ThreadLocal时,调用remove()方法,该方法删除了此变量的当前线程值。不要使用ThreadLocal.set(null),它只是查找与当前线程关联的Map并将键值中这个threadLocal对象所对应的值为null,并没有清除这个键值对。

最后

大家看完有什么不懂的可以在下方留言讨论,也可以关注我私信问我,我看到后都会回答的。也欢迎大家关注我的公众号:前程有光,马上金九银十跳槽面试季,整理了1000多道将近500多页pdf文档的Java面试题资料放在里面,助你圆梦BAT!文章都会在里面更新,整理的资料也会放在里面。谢谢你的观看,觉得文章对你有帮助的话记得关注我点个赞支持一下!

面试官:小伙子,你给我说一下Java中什么情况会导致内存泄漏呢?的更多相关文章

  1. 一线大厂面试官最喜欢问的15道Java多线程面试题

    前言 在任何Java面试当中多线程和并发方面的问题都是必不可少的一部分.如果你想获得更多职位,那么你应该准备很多关于多线程的问题. 他们会问面试者很多令人混淆的Java线程问题.面试官只是想确信面试者 ...

  2. 【Spring注解驱动开发】面试官:如何将Service注入到Servlet中?朋友又栽了!!

    写在前面 最近,一位读者出去面试前准备了很久,信心满满的去面试.没想到面试官的一个问题把他难住了.面试官的问题是这样的:如何使用Spring将Service注入到Servlet中呢?这位读者平时也是很 ...

  3. 面试官:如何在Integer类型的ArrayList中同时添加String、Character、Boolean等类型的数据? | Java反射高级应用

    原文链接:原文来自公众号:C you again,欢迎关注! 1.问题描述     "如何在Integer类型的ArrayList中同时添加String.Character.Boolean等 ...

  4. 搞定面试官:咱们从头到尾再说一次 Java 垃圾回收

    接着前几天的两篇文章,继续解析JVM面试问题,送给年后想要跳槽的小伙伴 万万没想到,面试中,连 ClassLoader类加载器 也能问出这么多问题..... 万万没想到,JVM内存区域的面试题也可以问 ...

  5. 面试官:我们来聊一聊Redis吧,你了解多少就答多少

    哈喽!大家好,我是小奇,一位不靠谱的程序员 小奇打算以轻松幽默的对话方式来分享一些技术,如果你觉得通过小奇的文章学到了东西,那就给小奇一个赞吧 文章持续更新,建议收藏关注 一.前言 作为一名Java程 ...

  6. 面试官:说一说Zookeeper中Leader选举机制

    哈喽!大家好,我是小奇,一位不靠谱的程序员 小奇打算以轻松幽默的对话方式来分享一些技术,如果你觉得通过小奇的文章学到了东西,那就给小奇一个赞吧 文章持续更新 一.前言 今天又是一个阳光明媚的一天,我又 ...

  7. 如何写出面试官欣赏的Java单例

    单例模式是一种常用的软件设计模式.在它的核心结构中只包含一个被称为单例的特殊类.通过单例模式可以保证系统中一个类只有一个实例. 今天我们不谈单例模式的用途,只说一说如果在面试的时候面试官让你敲一段代码 ...

  8. 【JAVA秒会技术之秒杀面试官】秒杀Java面试官——集合篇(一)

    [JAVA秒会技术之秒杀面试官]秒杀Java面试官——集合篇(一) [JAVA秒会技术之秒杀面试官]JavaEE常见面试题(三) http://blog.csdn.net/qq296398300/ar ...

  9. Java面试官最爱问的volatile关键字

    在Java的面试当中,面试官最爱问的就是volatile关键字相关的问题.经过多次面试之后,你是否思考过,为什么他们那么爱问volatile关键字相关的问题?而对于你,如果作为面试官,是否也会考虑采用 ...

随机推荐

  1. 全网通4G工业路由器模块和串口转网口/4G/有线/WiFi/LTE模块的实现原理

    随着现在信息化的高速发展,网络信息的需求量大增,在移动的4G流量的场合比如汽车上实现WiFi网络覆盖,户外wifi网络覆盖需求下,4G流量已经明显不够用,而网线到达的成本比较大,难以管控.在这市场痛点 ...

  2. 今日sb题之 sdnuoj 1064

    1 #include <iostream> 2 #include <string> 3 #include <stdio.h> 4 #include <cmat ...

  3. Kubernetes 搭建 ES 集群(存储使用 local pv)

    一.集群规划 由于当前环境中没有分布式存储,所以只能使用本地 PV 的方式来实现数据持久化. ES 集群的 master 节点至少需要三个,防止脑裂. 由于 master 在配置过程中需要保证主机名固 ...

  4. 【DeepLearning】AlexNet

    在前文中,我们介绍了LeNet的相关细节,它是由两个卷积层.两个池化层以及两个全链接层组成.卷积都是5*5的模板,stride =1,池化为MAX.整体来说它有三大特点:局部感受野,权值共享和池化.2 ...

  5. Luogu P2179 [NOI2012]骑行川藏

    题意 给定 \(n\) 个路段,每个路段用三个实数 \(s_i,k_i,v^\prime_i\) 描述,最小化 \[F(v_1,\cdots v_n)=\sum\limits_{i=1}^{n}\fr ...

  6. ModelSerializer 高级使用

    前言 ModelSerializer中还具有一些高级用法,如批量更新.批量删除.批量创建等. 但是批量过来的数据格式都需要与前端做好协商,什么样的数据格式是单条操作,什么样的数据格式是批量操作. 如下 ...

  7. Learn day1 变量/数据类型

    1.Python 简介 (1) 1989年开发的语言,创始人范罗苏姆(Guido van Rossum),别称:龟叔(Guido). (2) python具有非常多并且强大的第三方库,使得程序开发起来 ...

  8. C++代码雨

    闲逛的时候发现了一个很好玩的程序 摘自:https://blog.csdn.net/u012837895/article/details/20849967#comments 效果如下 #include ...

  9. Polyglot Translators: Let's do i18n easier! 一款国际化插件小助手!

    在做国际化文本有关的工作时, 是否厌倦了在不同应用或者网页之间频繁地切换进行中文, 繁体, 英文甚至韩文日文的文本翻译工作? 好吧, 我就是受不了频繁在进行文本字符串的转换, 还得跑到百度翻译上面搜索 ...

  10. 843. Guess the Word —— weekly contest 86

    题目链接:https://leetcode.com/problems/guess-the-word/description/ 占坑 据说要用启发式算法,可参考下述答案进行学习:https://leet ...