程序计数器
程序计数器是一块较小的内存空间,他的作用可以看做是当前线程所执行的字节码的行号指示器,每一个线程都有他自己的PC(程序计数器)寄存器
PC寄存器的大小是一个字长,因此它既能够持有一个本地指针,也能持有一个returnAddress,如果执行本地方法(非java方法),PC值为空(Undefined).
GC
一般是分代统计,年轻代(YoungGeneration)、老年代(Old Generation)和持久代(Permanent Generation, 其中持久代主要存放的是Java类的类信息,与垃圾收集要收集的Java对象关系不大。年轻代和年老代的划分是对垃圾收集影响比较大的。
所有新生成对象放到Young Generation中,其中一般分三个区,一个Eden,两个Survivor,新生对象在Eden中,经历过一次Minor GC后,如果还存活,年龄会增加一岁并移动到Survivor中,年轻代的回收算法为复制算法(复制算法的基本思想就是将内存分为两块,每次只用其中一块,当这一块内存用完,就将还活着的对象复制到另外一块上面。复制算法不会产生内存碎片)
在GC开始的时候,对象只会存在于Eden区和名为“From”的Survivor区,Survivor区“To”是空的。紧接着进行GC,Eden区中所有存活的对象都会被复制到“To”,而在“From”区中,仍存活的对象会根据他们的年龄值来决定去向。年龄达到一定年龄阈值的对象会被移动到年老代中,没有达到阈值的对象会被复制到“To”区域。经过这次GC后,Eden区和From区已经被清空。这个时候,“From”和“To”会交换他们的角色,也就是新的“To”就是上次GC前的“From”,新的“From”就是上次GC前的“To”。不管怎样,都会保证名为To的Survivor区域是空的。Minor GC会一直重复这样的过程,直到“To”区被填满,“To”区被填满之后,会将所有对象移动到年老代中
为什么Survivor需要两个,一个from,一个to?
答案是避免碎片化
看一下只有一个的情况:
产生的磁盘碎片空间:
结合之前的from和to就可以理解了
那么,Survivor为什么不分更多块呢?比方说分成三个、四个、五个?显然,如果Survivor区再细分下去,每一块的空间就会比较小,很容易导致Survivor区满,因此,我个人理解两块Survivor区是经过权衡之后的最佳方案。