「这是我参与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大小。