如果Web应用运行在JVM等具有垃圾回收功能的环境中,那么垃圾回收可能会对系统性能产生巨大的影响。理解垃圾回收机制有助于程序优化和参数调优,以及编写内存安全的代码。
以JVM为例,其内存主要可以分为堆(heap)和堆栈(stack)。
-
堆栈用于存储线程上下文信息,如方法参数、局部变量等。
-
堆则是存储对象的内存空间,对象的创建和释放、垃圾回收就在这里进行。
通过对对象生命周期的观察,发现大部分对象的生命周期都极其短暂,这部分对象产生的垃圾应该是被更快地收集,以释放内存,这就是JVM分代垃圾收集,其基本原理如下图所示。
在JVM分代垃圾回收机制中,将应用程序可用的堆空间分为年轻代(Young Generation)和年老代(Old Generation),又将年轻代分为Eden区、From区和To区,
-
1.新建对象总是在Eden区中被创建,
-
2.当Eden区空间已满,就触发一次Young GC(Garbage Collection,垃圾回收),将还被使用的对象复制到From区,这样整个Eden区都是未被使用的空间,可供继续创建对象,
-
3.当Eden区再次用完,再次出发一次Young GC,将Eden区和From区还在被使用的对象复制到To区,
-
4.下一次Young GC则是将Eden区和To区还在被使用的对象复制到From区。
-
5.因此,经过多次Young GC,某些对象会在From区和To区多次复制,如果超过某个阈值还未被释放,则将该对象复制到Old Generation。
-
6.如果Old Generation空间也已用完,那么会触发Full GC,即所谓的全量回收。
全量回收会对系统性能产生较大影响,因此应根据系统业务特点和对象生命周期,合理设置Young Generation和Old Generation大小,尽量减少Full GC。事实上,某些Web应用在整个运行期间可以做到从不进行Full GC。