① 内存泄露(Memory Leak)是指一个不再被使用的对象或者变量还在内存中占有存储空间。
在C/C++语言中,内存泄露出现在开发人员忘记释放已分配的内存就会造成内存泄露。
在java语言中引入垃圾回收机制,有GC负责进行回收不再使用的对象,释放内存。但是还是会存在内存泄露的问题。内存泄露主要有两种情况:
- 1.在堆中申请的空间没有释放。
- 2.对象已不再被使用(注意:这里的不在被使用是指对程序来说没有用处,如数据库连接使用后没有关。但是还是存在着引用),但是仍然在内存中保留着。GC机制的引入只能解决第一种情况,对于第2种情况无法保证不再使用的对象会被释放。java语言中的内存泄露主要指第2种情况。
内存泄露的原因:
- 1.静态集合类。如HashMap和Vector。这些容器是静态的,生命周期和程序的生命周期一致,那么在容器中对象的生命周期也和其一样,对象在程序结束之前将不能被释放,从而会造成内存泄露。
- 2.各种连接,如数据库连接,网络连接,IO连接,不再使用时如果连接不释放容易造成内存泄露。
- 3.监听器,释放对象时往往没有相应的删除监听器,可能会导致内存泄露。
内存溢出(OOM)是指程序在申请内存时没有足够的内存供使用,进而导致程序崩溃这是结果描述。
内存泄露(Memory Leak)最终会导致内存溢出。
② 垃圾回收机制。
垃圾回收主要针对的是堆区的回收,因为栈区的内存是随着线程而释放的。
堆区分为三个区:年轻代(Young Generation)、年老代(Old Generation)、永久代(Permanent Generation,也就是方法区)。
年轻代:对象被创建时(new)的对象通常被放在Young(除了一些占据内存比较大的对象),经过一定的Minor GC(针对年轻代的内存回收)还活着的对象会被移动到年老代(一些具体的移动细节省略)。
年老代:就是上述年轻代移动过来的和一些比较大的对象。Minor GC(FullGC)是针对年老代的回收
永久代:存储的是final常量,static变量,常量池。
str3,str4都是直接new的对象,而substring的源代码其实也是new一个string对象返回,如下图:
经过fullgc之后,年老区的内存回收,而年轻区的占了15个,不算PermGen。