JAVA中内存泄露和内存溢出
一、为什么要了解内存泄露和内存溢出
1.内存泄漏一般是程序员编写的代码有误导致的,了解内存泄漏的情况可以避免不必要的内存泄漏,让程序员提高自己编码水平。
2.通过了解内存溢出常见情况,可以快速准确地找到问题所在,缩短解决问题的时间。
二、内存泄漏和内存溢出的概念区分
1.内存泄漏,指的是,程序动态分配内存给一些临时对象,但是这些临时对象却没有GC所回收,始终占内存,即使没用了也始终占着内存,这就是内存泄漏。
2.内存溢出,指的是,没有被分配到足够的内存而导致的错误。
注意:看来内存泄漏是可能导致内存溢出的一种原因,并不是唯一原因。
三、内存泄漏的几种场景:
1.生命周期较长的对象中存了生命周期短的对象
这是内存泄漏的场景中最常见的一种,例如,在全局静态map中存了局部变量没有清空操作,随着时间的推移,map越来越大,因此造成内存泄漏。
2.修改了HashSet中对象计算哈希值的字段
当对象存入HashSet集合以后,就不能修改计算哈希值的字段了,否则修改后的哈希值与最初存入的哈希值就不同了。在这样的情况下,即使是在contains方法中使用该对象的当前引用作为参数也是找不到该对象的。这样就无法删除HashSet集合中的这个对象,因此导致内存泄漏。
3.机器的连接数和关闭时间设置
长时间开着非常耗费资源的连接也会造成内存泄漏。
四、内存溢出的几种情况:
1.方法区内存溢出(outOfMemoryError:permgem space)
在jvm规范中,方法区主要存放的是类信息、常量、静态变量等。
所以如果程序加载的类过多,或者使用反射、gclib等这种动态代理生成类的技术,就可能导致该区发生内存溢出,一般该区发生内存溢出时的错误信息为:
outOfMemoryError:permgem space
2.线程栈溢出(java.lang.StackOverflowError)
线程栈时线程独有的一块内存结构,所以线程栈发生问题必定是某个线程运行时产生的错误。
一般线程栈溢出是由于递归太深或方法调用层级过多导致的。
发生栈溢出的错误信息为:
java.lang.StackOverflowError
五、避免内存泄漏和内存溢出的几种方法:
1、尽早释放无用对象的引用
2、使用字符串处理,避免使用String,应大量使用StringBuffer,每一个String对象都得独立占用内存一块区域
3、尽量少用静态变量,因为静态变量存放在方法区,方法区基本不会被垃圾回收
4、避免在循环中创建对象
5、开启大型文件或从数据库一次拿了太多的数据很容易造成内存溢出,所以在这些地方要大概计算一下数据量的最大值是多少,并且设定所需最小及最大的内存空间值。