java面试总结(四)jvm内存模型

一、java内存模型
在这里插入图片描述

1、程序计数器(线程私有):
(1)字节码解释器工作是就是通过改变这个计数器的值来选取下一条需要执行指令的字节码指令,分支、循环、跳转、异常处理、线程恢复等基础功能都需要依赖计数器完成。
(2)如果线程正在执行一个 Java 方法,这个计数器记录的是正在执行的虚拟机字节码指令的地址;如果正在执行的是 Native 方法,这个计数器的值则为 (Undefined)。此内存区域是唯一一个在 Java 虚拟机规范中没有规定任何 OutOfMemoryError 情况的区域。

2、java 虚拟机栈(线程私有)
(1)生命周期和线程一致。描述的是 Java 方法执行的内存模型:每个方法在执行时都会床创建一个栈帧(Stack Frame)用于存储局部变量表、操作数栈、动态链接、方法出口等信息。每一个方法从调用直至执行结束,就对应着一个栈帧从虚拟机栈中入栈到出栈的过程。
(2)局部变量表:存放了编译期可知的各种基本类型(boolean、byte、char、short、int、float、long、double)、对象引用(reference 类型)和 returnAddress 类型(指向了一条字节码指令的地址),会抛出StackOverflowError(线程请求的栈深度大于虚拟机所允许的深度)和OutOfMemoryError(如果虚拟机栈可以动态扩展,而扩展时无法申请到足够的内存)。

3、本地方法栈(线程私有)
和虚拟机栈类似,主要为虚拟机使用到的Native方法服务。也会抛出StackOverflowError 和OutOfMemoryError。

4、Java堆(线程共享)
被所有线程共享的一块内存区域,在虚拟机启动的时候创建,用于存放对象实例,可以按照可扩展来实现(通过-Xmx 和-Xms 来控制),当堆中没有内存可分配给实例,也无法再扩展时,则抛出OutOfMemoryError异常。

5、方法区(线程共享)
被所有方法线程共享的一块内存区域,用于存储已经被虚拟机加载的类信息,常量,静态变量等,这个区域的内存回收目标主要针对常量池的回收和堆类型的卸载。

二、判断对象是否存活

    1、Java 堆和方法区中,一个接口中的多个实现类需要的内存可能不一样,一个方法中的多个分支需要的内存也可能不一样,我们只有在程序处于运行期才知道那些对象会创建,这部分内存的分配和回收都是动态的,垃圾回收器所关注的就是这部分内存。

    2、在垃圾回收之前,需要判断哪些对象是“存活的”,哪些是“死”的。

     (1)引用计数法:给对象添加一个引用计数器,但是难以解决循环引用问题。
     (2)可达性分析法:通过一系列的 ‘GC Roots’ 的对象作为起始点,从这些节点出发所走过的路径称为引用链,当一个对象到 GC Roots 没有任何引用链相连的时候说明对象不可用。
     (3)可作为 GC Roots 的对象:虚拟机栈(栈帧中的本地变量表)中引用的对象、
 方法区中类静态属性引用的对象、方法区中常量引用的对象、本地方法栈中 JNI(即一般说的 Native 方法) 引用的对象。

三、内存分配

    1、当代主流虚拟机(Hotspot VM)的垃圾回收都采用“分代回收”的算法。“分代回收”是基于这样一个事实:对象的生命周期不同,所以针对不同生命周期的对象可以采取不同的回收方式,以便提高回收效率。Hotspot VM将内存划分为不同的物理区,就是“分代”思想的体现。JVM内存主要由新生代、老年代、永久代构成。
 
    (1) 新生代(Young Generation):大多数对象在新生代中被创建,其中很多对象的生命周期很短。每次新生代的垃圾回收(又称Minor GC)后只有少量对象存活,所以选用复制算法,只需要少量的复制成本就可以完成回收。
   
    (2)新生代内又分三个区:一个Eden区,两个Survivor区(一般而言),大部分对象在Eden区中生成。当Eden区满时,还存活的对象将被复制到两个Survivor区(中的一个)。当这个Survivor区满时,此区的存活且不满足“晋升”条件的对象将被复制到另外一个Survivor区。对象每经历一次Minor GC,年龄加1,达到“晋升年龄阈值”后,被放到老年代,这个过程也称为“晋升”。显然,“晋升年龄阈值”的大小直接影响着对象在新生代中的停留时间,在Serial和ParNew GC两种回收器中,“晋升年龄阈值”通过参数MaxTenuringThreshold设定,默认值为15。
   
    (3)老年代(Old Generation):在新生代中经历了N次垃圾回收后仍然存活的对象,就会被放到年老代,该区域中对象存活率高。老年代的垃圾回收(又称Major GC)通常使用“标记-清理”或“标记-整理”算法。整堆包括新生代和老年代的垃圾回收称为Full GC(HotSpot VM里,除了CMS之外,其它能收集老年代的GC都会同时收集整个GC堆,包括新生代)。

    (4)永久代(Perm Generation):主要存放元数据,例如Class、Method的元信息,与垃圾回收要回收的Java对象关系不大。相对于新生代和年老代来说,该区域的划分对垃圾回收影响比较小。

参考博客:https://blog.csdn.net/qq_41701956/article/details/81664921
https://www.cnblogs.com/feiyudemeng/p/8276911.html(GC调优)

发布了11 篇原创文章 · 获赞 7 · 访问量 5037

猜你喜欢

转载自blog.csdn.net/rg201612/article/details/104700842