JVM

JVM内存模型

jvm内存模型

JVM的内存模型主要分为5个区域,java运行时,JVM拿到了自己能支配的内存之后,将内存进行了区域分割,分别是 栈区:存储函数运行过程中的一些临时的局部变量(存储对象的引用类型,存储的是一个对象的地址,最终指向堆区存储的对象),基本数据类型也存储在栈区

栈、本地方法栈、程序计数器 这三个部分是线程私有的,也就是说在运行过程中有多少个线程就会有多少个栈区,而堆、方法区是全局共享的

Java 字符串常量存放在堆内存还是JAVA方法区? JDK1.7 及之后版本的 JVM 已经将运行时常量池从方法区中移了出来,在 Java 堆(Heap)中开辟了一块区域存放运行时常量池。 JDK1.8开始,取消了Java方法区,取而代之的是位于直接内存的元空间(metaSpace)。

GC 垃圾回收机制

1.哪些内存需要回收?

通过可达性分析,判断对象是否存活。如果一个对象没有被GC Roots直接引用或者间接引用,那就是不可达的,将被列为回收对象。

GC Roots通常是指存储在栈、本地方法栈、方法区的引用。

2.回收算法

gc 2.1 标记-清除算法
先标记出所有需要回收的对象,然后进行统一回收 缺点:产生大量不连续的碎片

2.2 标记-整理算法
先进行标记,然后将存活的对象向一端移动,最后将存活边界以外的对象全部清除 缺点:对象移动代价太大,消耗较多的时间

2.3 复制算法
将内存划分为两个相等区域,即每次使用内存的一半区域,需要GC时,将存活的对象复制到未使用的区域连续存储,然后执行GC 缺点:浪费一半内存

2.4 分代收集算法(实际GC过程)
将Java堆分为新生代和老年代。
新生代:新生代中的对象大部分是“朝生夕死”的,所以类似于复制算法,将内存划分为一块大的Eden空间和两个小的Survivor空间,大小E:S0:S1=8:1:1。
新生对象在Eden区分配,当Eden区空间不足时,需要执行YoungGC。S0与S1交替工作。(1)将E、S0存活的对象复制到S1区,然后清除E、S0;(2)将E、S1存活的对象复制到S0区,然后清除E、S1。

老年代:(1)大对象直接进入老年代,因为大对象复制消耗的时间比较大;(2)长期存活的对象直接进入老年代。每GC一次,对象的年龄计数器Age就会+1,当对象age>6时(默认最大为15,一般还要×个比率,CMS算出来为6),会将对象存储到老年代。
当Old区存储满了时,执行FullGC,清理Old区,通常使用标记-清除(Serial Old和Parallel Old)或者标记-整理(CMS)算法。FullGC会导致"Stop the world",就是暂停java程序的执行,全力进行垃圾收集。

总结一下:新生代主要使用复制算法,老年代主要使用标记清除或者标记整理算法

CMS垃圾收集器

G1垃圾收集器