java 程序 jvm 内存分配使用 及 相关概念详解
JAVA堆内存管理是影响性能主要因素之一。
堆内存溢出是JAVA项目非常常见的故障,在解决该问题之前,必须先了解下JAVA堆内存是怎么工作的。
1. jvm 内存
(图为 java8之前)
JVM 内存划分为堆内存和非堆内存,堆内存分为年轻代(Young Generation)、老年代(Old Generation),非堆内存就一个永久代(Permanent Generation)
年轻代又分为 Eden 和 Survivor 区。Survivor 区由 FromSpace 和 ToSpace 组成。Eden 区占大容量,Survivor 两个区占小容量,默认比例是 8:1:1
堆内存用途:存放的是对象,垃圾收集器就是收集这些对象,然后根据 GC 算法回收。
非堆内存用途:永久代,也称为方法区,存储程序运行时长期存活的对象,比如类的元数据、方法、常量、属性等。
在 JDK1. 8版本 废弃了 永久代,替代的是元空间(MetaSpace),元空间 与 永久代上类似,都是方法区的实现,他们最大区别是:元空间 并不在 JVM 中,而是使用本地内存。
元空间有注意有两个参数:
MetaspaceSize :初始化 元空间大小,控制发生 GC 阈值,不断增大到 MaxMetaspaceSize.每次增大都 FGC
MaxMetaspaceSize : 限制 元空间大小上限
2. 为什么移除永久代?
移除永久代原因:为融合 HotSpot JVM 与 JRockit VM(新JVM技术)而做出的改变,因为 JRockit 没有永久代。
有了元空间就不再会出现永久代OOM问题了!
3. 分代概念
各区内的对象走向:
新生成的对象首先放到 年轻代 Eden 区
当 Eden 空间满了,触发 Minor GC
存活下来的对象移动到 Survivor0 区
Survivor0 区满后触发执行 Minor GC
Survivor0 区存活对象移动到 Suvivor1 区 ;这样保证了一段时间内总有一个 survivor 区为空
经过多次 Minor GC 仍然存活的对象移动到 老年代。
老年代存储长期存活的对象,占满时会触发 Major GC = Full GC
名词解释:
Minor GC : 清理年轻代 ,不过这个过程非常短暂。
Major GC : 清理老年代
Full GC : 清理整个堆空间,包括 年轻代 和 永久代
所有 GC 期间会停止所有线程 等待 GC 完成,所以对响应要求高的应用尽量减少发生 Major GC 和 Full GC,避免响应超时。Minor GC 时间很短。
4.为什么分代?
将对象根据存活概率进行分类,对存活时间长的对象,放到固定区,从而减少扫描垃圾时间及GC 频率。针对分类进行不同的垃圾回收算法,对算法扬长避短。
5.为什么 survivor 分为两块相等大小的幸存空间
主要为了解决碎片化。如果内存碎片化严重,也就是两个对象占用不连续的内存,已有的连续内存不够新对象存放,就会触发 GC。
共 0 条评论