GC内存管理——内存溢出和内存泄漏

内存溢出和内存泄漏

java内存管理

  • 在java中,我们需要通过new关键字对每一个对象申请内存空间(基本类型除外),所有的对象都是在堆(Heap)中分配空间的。
  • 在java中,内存分配是管理员决定的,但是内存的释放是由GC完成,这样收支两线机制确实简化了程序员的工作量。
  • 垃圾回收机制加重了jvm的工作,这也是java程序执行速度比较慢的原因之一。GC为了能够正确、及时释放不再被引用的对象,GC必须监控每一个对象的运行状态,包括对象的内存申请、引用、被引用、赋值等,GC都需要进行监控。
  • 在Java中,使用有向图的方式进行内存管理,精度高,但是效率较低,可以处理引用循环等问题。例如有三个对象互相引用,只要和根进程是不可到达的,就可以被GC回收。
  • 另外一种内存管理技术是使用计数器,例如COM模型采用计数器方式管理构件,它与有向图相比,精度低,但执行效率高。

内存泄漏

内存泄漏是堆中的存在无用但可达的对象,GC无法回收。

当存在以下两种情况的实例时

  • 对象是可达的。即在有向图中,存在通过达到该对象,GC不会回收
  • 对象是无用的。即程序以后不会再使用这些对象。
    那么这些对象是无用的,但是他们依然占用资源,不会被GC回收,最后导致内存泄漏。
内存泄漏分类
  • 常发性内存泄漏
    发生内存泄漏的代码会被多次执行到,每次被执行的时候都会导致一块内存泄漏。
  • 偶发性内存泄漏
    发生内存泄漏的代码只有在某些特定的环境或操作过程下才会发生。常发性和偶发性是相对的。对于特定的环境,偶发性的也许就变成了常发性内存泄漏。所以测试环境和测试方法对检查内存泄漏至关重要。
  • 一次性内存泄漏
    发生内存泄漏的代码只会被执行一次,或者由于算法上的缺陷,导致总会有一块内存发生泄漏。比如在类的构造函数中分配内存,但是却没有释放该内存,所以内存泄漏只会发生一次。
  • 隐式内存泄漏
    程序在运行过程中不停的分配内存,但是知道结束的时候才释放内存。严格的说这里并没有发生内存泄漏,因为最终程序释放了所有申请的内存。但是对于一个服务器程序,需要运行几天,几周甚至几个月,不及时释放内存肯能导致最终耗尽系统的所有内存。所以我们称这类内存泄漏为隐式泄漏。
  • 通常,GC的线程的优先级别较低。JVM调用GC的策略也有很多种,有的是内存使用到达一定程度时,GC才开始工作,也有定时执行的,有的是平缓执行GC,有的是中断是执行GC。但通常来说,我们不需要关心这些。除非在一些特定的场合,GC的执行影响应用程序的性能,例如对于基于Web的实时系统,如网络游戏等,用户不希望GC突然中断应用程序执行而进行垃圾回收,那么我们需要调整GC的参数,让GC能够通过平缓的方式释放内存。

内存泄漏实例

Vector v=new Vector(10);
for (int i=1;i<100; i++)
{
    Object o=new Object();
    v.add(o);
    o=null; 
}

在这个例子中,我们循环申请对象o,并将o放入容器v中,虽然我们释放了o,但是由于容器还引用这个对象,所以GC是不会回收该对象的。我们需要释放容器才能被GC回收。

内存溢出

如果内存泄漏严重,最终会导致内存溢出。内存溢出是空间不足的溢出,主要分为PermGen space不足、堆不足、栈不足
**1、OutOfMemoryError: PermGen space
PermGen Space指的是内存的永久保存区,该块内存主要是被JVM用来存放class和mete信息的,当class被加载loader的时候就会被存储到该内存区中,与存放类的实例的heap区不同,java中的垃圾回收器GC不会在主程序运行期对PermGen space进行清理。
因此,程序启动时如果需要加载的信息太多,超出这个空间的大小,则会发生溢出。
解决方案:增加空间分配——增加java虚拟机中的XX:PermSize和XX:MaxPermSize参数的大小,其中XX:PermSize是初始永久保存区域大小,XX:MaxPermSize是最大永久保存区域大小。
2、OutOfMemoryError:Java heap space
heap是Java内存中的堆区,主要用来存放对象,当对象太多超出了空间大小,GC又来不及释放的时候,就会发生溢出错误。即内存泄露越来越严重时,可能会发生内存溢出。
解决方案:
(1)、检查程序,减少大量重复创建对象的死循环,减少内存泄露。
(2)、增加Java虚拟机中Xms(初始堆大小)和Xmx(最大堆大小)参数的大小。
3、StackOverFlowError
stack是Java内存中的栈空间,主要用来存放方法中的变量,参数等临时性的数据的,发生溢出一般是因为分配空间太小,或是执行的方法递归层数太多创建了占用了太多栈帧导致溢出。
解决方案:修改配置参数-Xss参数增加线程栈大小之外,优化程序是尤其重要。

你可能感兴趣的:(JVM,内存泄漏,java,jvm)