一、内存溢出
1、(out of memory):指程序在申请内存时,没有足够的内存空间供其使用,出现out of memory,比如申请了10个字节的空间,但是你在这个空间写入11或以上字节的数据,出现溢出。
2、产生原因:
a、jvm内存过小,
b、程序不严谨,产生过多的垃圾。
3、程序体现:
a、内存中加载的数据量过于庞大,如一次从数据库中取出过多数据。
b、集合类中有对对象的引用,使用完后未清空,使得jvm不能回收。
c、代码中存在死循环或循环产生过多重复的对象实体。
d、启动参数内存值设置得过小。
e、使用的第三方软件中的bug。
4、解决办法:
a、增加JVM的内存大小。
b、如果是tomcat,则修改启动参数和配置信息,然后重启tomcat,设置就能生效了。
c、检查代码中是否有死循环或递归调用,检查是否有大循环重复产生新对象实体;优化程序,释放垃圾。
d、避免死循环,防止一次载入太多的数据,提高程序健壮性及时释放。因此,从根本上解决Java内存溢出的唯一方法就是修改程序,及时地释放没用的对象,释放内存空间。
二、内存泄漏
1、(memory leak):你用new申请了一块内存,后来很长时间都不再使用了(按理应该释放),但是因为一直被某个或某些实例所持有导致 GC 不能回收,也就是该被释放的对象没有释放。
2、在Java中,内存泄漏就是存在一些被分配的对象,这些对象有下面两个特点:
1):首先,这些对象是可达的,即在有向图中,存在通路可以与其相连。
2):其次,这些对象是无用的,即程序以后不会再使用这些对象。
如果对象满足这两个条件,这些对象就可以判定为Java中的内存泄漏,这些对象不会被GC回收,然而它却占用内存。
3、关于内存泄漏的处理方法就是提高程序的健壮性,因为内存泄漏时纯代码层面的问题。
三、二者关系
内存泄露最终会导致内存溢出。
相同点:都会导致应用程序出现问题,性能下降或挂起。
不同点:
1):内存泄漏是导致内存溢出的原因之一,内存泄露积累起来将导致内存溢出。
2):内存泄露可以通过完善代码来避免,内存溢出可以通过调整配置来减少发生频率,但无法彻底避免。
四、举例:
一台生产环境机器每次运行几天之后就会莫名其妙的宕机,分析日志之后发现在tomcat刚启动的时候内存占用比较少,但是运行个几天之后内存占用越来越大,通过jmap命令可以查询到一些大对象引用没有被及时GC,这里就要求解决内存泄露的问题。
Java的内存泄露多半是因为对象存在无效的引用,对象得不到释放,如果发现Java应用程序占用的内存出现了泄露的迹象,那么我们一般采用下面的步骤分析:
1、用工具生成java应用程序的heap dump(如jmap)
2、使用Java heap分析工具(如MAT),找出内存占用超出预期的嫌疑对象
3、根据情况,分析嫌疑对象和其他对象的引用关系。
4、分析程序的源代码,找出嫌疑对象数量过多的原因。