一、 垃圾回收
JVM中用heap堆来存储运行时数据,所有类实例和数组由堆分配内存,JVM启动时创建堆(heapmemory),在堆以外的内存叫非堆(non-heapmemory). 其中,堆内存分为新生代代和年老代,非堆内存主要是Permanent区域,主要用于存储一些类的元数据,常量池等信息。
1.堆(HeapSpace)
所有new出来的对象内存都分配在堆中,堆被分成新生代(YongGeneration)和老年代(OldGeneration),新生代又分成Eden和两个Survivor区。
MinorGC
新生代是所有新对象产生的地方。当新生代内存空间被用完时,就会触发垃圾回收。这个垃圾回收叫做MinorGC。新生代被分为3个部分——Enden区和两个Survivor区。新对象在新生代产生,当新生代空间占满后,会触发MinorGC开始垃圾回收,大多数新建对象位于Eden区,对象的年龄为“0”,Eden区满后触发一次MinorGC,存活下来的对象转到survivor0区,同时对象年龄增长为“1”, 并清除整个Eden内存区域中的非可达对象。survivor0区满后触发执行MinorGC,survivor0区存活对象全部转入survivor1区,这样保证一段时间内总有一个survivor区为空。经过多次MinorGC仍然存活的对象会转入老年代,这是由设定的年龄阈值来决定的。最后,清除所有在Eden内存区域和Survivor0内存区域的非可达对象。
MajorGC:major garbage collection(也是Full gc)
老年代空间存储长期存活的对象,老年代占满时会触发MajorGC,也就是新生代,老年代都进行回收,花费时间较长,由于垃圾回收会导致“stoptheworld”事件,即所有线程都会停下来等待垃圾回收执行完成,所以对响应要求高的应用应尽量减少发生MajorGC,如微博后台程序发生MajorGC就会导致前台页面刷新超时,若是股票等实时交易应用发生MajorGC导致响应超时,可能会给客户带来损失,这都是系统调优要考虑到的问题。
在分代收集算法中,由于新生代中对象的存活率低,通常使用复制算法Mark-Copy进行垃圾回收,老年代一般使用”标记-清理”或”标记-整理”算法回收存活率较高的对象。
2.永久代
永久代(PermanentGeneration),用来保存程序运行时长期存活的对象,如类的元数据。
问题:“地球人都知道,Java有个东西叫垃圾收集器,它让创建的对象不需要像c/cpp那样delete、free掉,你能不能谈谈,GC是在什么时候,对什么东西,做了什么事情?”
- 系统自身决定,不可预测的时间/调用System.gc()的时候。
- 超出作用域的对象/引用计数为空的对象。从gc root开始搜索,搜索不到的对象。从gc root搜索不到,而且经过第一次标记、清理后,仍然没有复活的对象。