JVM(六)--垃圾回收机制(二)

149 阅读3分钟

「这是我参与11月更文挑战的第13天,活动详情查看:2021最后一次更文挑战

接上一篇 JVM(五)--垃圾回收机制(一) 我们这次主要分析内存泄漏和内存溢出

一、 Java 堆内存

用来存放由new创建的对象实例和数组 Java堆是所有线程共享的一块内存区域,在虚拟机启动时创建,此内存区域的唯一目的就是存放对象实例 。   Java堆是垃圾收集器管理的主要区域。

二、 JAVA 中的内存泄露

一般来说内存泄漏有两种情况。一是在堆中分配的内存,在没有将其释放掉的时候,就将所有能访问这块内存的方式都删掉;另一种情况则是在内存对象明明已经不需要的时候,还仍然保留着这块内存和它的访问方式(引用)。第一种情况,在Java中已经由于垃圾回收机制的引入,得到了很好的解决。所以,Java中的内存泄漏,主要指的是第二种情况。

1. 静态集合类引起的内存泄露

像HashMap、Vector等的使用最容易出现内存泄漏,这些静态变量的生命周期和应用程序一致,他们所引用的对象也不能被释放

2. 监听器引起的内存泄露

我们都使用过监听器,比如addXXXListener(),通常一个应用当中会用到很多监听器,但是往往在释放对象的时候却没有去删除这些监听器,从而会增加内存泄漏的机会

3. 各种连接引起的内存泄露

比如我们使用数据库,首先会建立与数据库的连接,当不使用的时候,需要调用close()方法将其关闭,只有连接被关闭,垃圾回收器才会回收对应的对象。 比如:数据库连接、网络连接、io连接等

4. 内部类持有外部模块引用引起的内存泄露

这个内部类引用外部类,即使那个外部类实例对象不再被使用,但由于内部类持有外部类的实例对象,这个外部类对象将不会被垃圾回收,这也会造成内存泄露

5. 单例模式引起的内存泄露

不正确使用单例模式,就会容易引起内部泄漏,单例对象在初始化后将在JVM的整个生命周期中存在,如果单例对象持有外部类的引用,那么这个对象讲不能被JVM正常回收,会导致内存泄漏

三、 JAVA 中的内存溢出

内存溢出是在程序申请内存时,没有足够空间供它使用,有4种常见内存溢出

  • 栈溢出(java.lang.StackOverflowError : Thread Stack space)

    优化:通过Xss参数调整
    
  • 堆溢出(java.lang.OutOfMemoryError: Java heap space)

    优化:通过-Xmn(最小值)–Xms(初始值) -Xmx(最大值)参数手动设置 Heap(堆)的大小
    
  • 方法区和运行时常量池溢出(java.lang.OutOfMemoryError: PermGen space)

    优化:通过MaxPermSize参数设置PermGen space大小。