Java堆区的认识

读书笔记–谢宇《Java特种兵(上册)》 Kay 2017.7.1整理

Java中的“堆”区,也就是Heap,主要包括两大块:YoungOld ,2个板块又有自己的区分,但是关于内存回收的方式又有不同。一般来说,Young空间相对Old会小很多,涉及到具体的场景和配置。

Young 空间

Young空间被分为2各部分和3个板块,也就是:1个Eden区 和 2个 Survivor 区

  1. Eden 区默认会存放了 通过newnewInstance()等创建的对象
  2. 2个Survivor区通常称为S0、S1,理论上2个区是一样大的(如果有其他参数配置外)

Eden区和Survivor如何配合工作的:

  1. 不断创建对象的过程中,Eden区域会被装满,满的时候就开始做Young GC(也称为Minor GC),在Young空间第1次 GC的时候,会找出Eden区域存活的对象,并将这些对象存放到S0或S1区域中的一个中去
  2. 假设第1次 GC选择了S0存放对象,如果S0的空间放满了,剩下的对象就会放到Old区去。然后Eden区将会被清空。此时S1区域是空的
  3. 第2次 Eden区满的时候,就会将 Eden区和S0区中存活的对象一起迁移到S1区域中(如果S1放不下,则会放到Old区),最后清空Eden区和S0区此时S0就会成为空的
  4. 以后的操作依次类推,在这个过程中,S0、S1始终有一个是空的。

Minor GC简单示意图
Java堆区的认识

结论:
- 在Young空间清理的时候,由于活下来的对象是少数,所以寻找这些对象就会很快。
- 存活的对象不多,所以存放它们需要的空间也不大,所以就有了Survivor区域,也不会太大
- 如果对象的存活周期很长,程序跑得很慢,被清理的概率就会很低,Survivor区域放不下时就会放在Old区域

Old 区域

上面说了,存活时间较长的对象会进入Old区域,那么进入Old区域会带来什么影响呢?
Old区域又叫做老年代,老年代存放了很多对象,这些对象要么“足够老”,要么是在Minor GC时放不下而进入Old区域。当Old区域满时,就会做Full GC,Full GC的任务是在Old区域中寻找存活的对象,但是在这个区域中大多数对象都是活的,所以这个时候寻找起来就比较麻烦,效率比较低。
如果Full GC频繁,在里面的存活的对象子在短时间内无法释放,那么Full GC的时间越长,就会有越多的请求得不到响应或者响应很慢,内存无法释放,越来越多的对象进入Old区,产生连锁效应,这是要避免的情况。
另一方面,在Full GC的时候,要对Old区域进行清理,通常会做压缩碎片的操作,碎片也就是清除对象时产生的。如果活着的对象越多,那么整理碎片也会越麻烦(因为是顺序移动)。

关于永久代 PermGen

Java 8这个区域没有,只在Hotspot VM中有
以后Hotspot VM中是打算去掉Perm这个块空间的,其他厂商的JVM也没有这个块空间
- Class加载是被加载到了PermGen中(永久代中最大用户)
- 常量池(比如String对象的intern()方法会在常量池中查找相同值,找到了就直接返回,没找到就会存一个String对象在常量池中)

相关文章:

  • 2021-04-08
  • 2021-08-29
  • 2022-02-22
  • 2021-12-09
  • 2021-07-16
  • 2021-11-23
猜你喜欢
  • 2021-09-17
  • 2021-07-01
  • 2021-12-27
  • 2021-11-24
  • 2021-07-18
  • 2021-07-05
  • 2022-12-23
相关资源
相似解决方案