本文内容收拾自 博学谷狂野架构

敞开生长之旅!这是我参与「日新方案 2 月更文挑战」的第 6 天,点击检查活动概况

运转时数据区都包括什么

为什么这11道JVM面试题这么重要(附答案)

虚拟机的根底面试题

  1. 程序计数器
  2. Java 虚拟机栈
  3. 本地办法栈
  4. Java 堆
  5. 办法区

程序计数器

程序计数器是线程私有的,并且是JVM中仅有不会溢出的区域,用来保存线程切换时的履行行数

程序计数器(Program Counter Register)是一块较小的内存空间,能够看作是当时线程所履行字节码的行号指示器。分支、循环、跳转、反常处理、线程康复等根底功能都需求依靠这个计数器完结。

由于 Java 虚拟机的多线程是经过线程轮流切换并分配处理器履行时刻的方式完结的。为了线程切换后能康复到正确的履行方位,每条线程都需求一个独立的程序计数器,各线程之间的计数器互不影响,独立存储。

  1. 假如线程正在履行的是一个 Java 办法,计数器记载的是正在履行的虚拟机字节码指令的地址;
  2. 假如正在履行的是 Native 办法,这个计数器的值为空。

程序计数器是仅有一个没有规定任何 OutOfMemoryError 的区域

虚拟机栈

Java 虚拟机栈(Java Virtual Machine Stacks)是线程私有的,生命周期与线程相同。

虚拟机栈描述的是 Java 办法履行的内存模型:每个办法被履行的时分都会创立一个栈帧(Stack Frame),存储

每一个办法被调用到履行完结的进程,就对应着一个栈帧在虚拟机栈中从入栈到出栈的进程

组成部分
  • 局部变量表
  • 操作数栈
  • 动态链接
  • 办法出口
反常状况
  • StackOverflowError:线程请求的栈深度大于虚拟机所允许的深度
  • OutOfMemoryError:虚拟机栈扩展到无法请求足够的内存时

本地办法栈

本地办法栈(Native Method Stacks)为虚拟机运用到的 Native 办法服务

Java 堆

Java 堆(Java Heap)是 Java 虚拟机中内存最大的一块。Java 堆在虚拟机启动时创立,被一切线程同享。

效果:寄存目标实例。废物搜集器首要办理的便是 Java 堆。Java 堆在物理上能够不连续,只需逻辑上连续即可。

包括元素
  • 目标
  • 数组
  • 非静态变量
有什么反常
  • java.lang.OutOfMemoryError: Java heap space:这种是java堆内存不行,一个原因是真不行,另一个原因是程序中有死循环
  • java.lang.OutOfMemoryError: GC overhead limit exceeded:JDK6新增过错类型,当GC为开释很小空间占用很多时刻时抛出

办法区

办法区(Method Area)被一切线程同享,用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。

和 Java 堆相同,不需求连续的内存,能够挑选固定的大小,更能够挑选不完结废物搜集。

废物收回算法有哪些

常用的废物收回算法有如下四种:符号-铲除、仿制、符号-收拾和分代搜集。

符号-铲除算法

从算法的名称上能够看出,这个算法分为两部分,符号和铲除。首要符号出一切需求被收回的目标,然后在符号完结后一致收回掉一切被符号的目标。

这个算法简略,可是有两个缺点:

  • 一是符号和铲除的功率不是很高;
  • 二是符号和铲除后会产生很多的内存碎片,导致可用的内存空间不连续,当分配大目标的时分,没有足够的空间时不得不提早触发一次废物收回。

履行进程如下图

为什么这11道JVM面试题这么重要(附答案)

仿制算法

为了处理功率问题,一种称为“仿制”(Copying)的搜集算法出现了,他将可用内存按容量划分为大小持平的两块,每次只运用其中的一块。当这块的内存用完了,就将还存活这的目标仿制到另外一块上面,然后再把已运用过的内存空间一次收拾掉。这样使得每次都是对整个半区进行内存收回,内存分配时也就不用考虑内存碎片等复杂状况,只需移动堆顶指针,按顺序分配内存即可,完结简略,运转高效。只是这种算法的代价是将内存缩小为了本来的一半,未免太高了一点。

优缺点

  • 长处:简略高效
  • 缺点:代价是将内存缩小为本来的一半,代价高

履行进程如下图

为什么这11道JVM面试题这么重要(附答案)

符号-收拾算法

仿制搜集算法在目标存活率较高时就要进行较多的仿制操作,功率将会变低。更要害的是假如不想糟蹋50%的空间就要运用额外的空间进行分配担保(Handle Promotion当空间不行时,需求依靠其他内存),以应对被运用的内存中一切目标都100%存活的极点状况

对于“符号-收拾”算法,符号进程仍与“符号-铲除”算法相同,可是后续步骤不是直接对可收回目标进行收拾,而是让一切的存活目标都向一端移动,然后直接收拾掉端鸿沟以外的内存,”符号-收拾“算法示意图如下:

为什么这11道JVM面试题这么重要(附答案)

符号-收拾算法处理了仿制算法多仿制功率低、空间利用率低的问题,一起也处理了内存碎片的问题。

分代搜集算法

根据目标生存周期的不同将内存空间划分为不同的块,然后对不同的块运用不同的收回算法。一般把Java堆分为新生代和老时代,新生代中目标的存活周期短,只有少数存活的目标,所以能够运用仿制算法,而老时代中目标存活时刻长,而且目标比较多,所以能够采用符号-铲除和符号-收拾算法。

为什么这11道JVM面试题这么重要(附答案)

判别目标是否有用

引证计数算法

为什么这11道JVM面试题这么重要(附答案)

给目标添加一个引证计数器,每当一个当地引证它时,数据器加1;当引证失效时,计数器减1;计数器为0的即可被收回。

  • 长处:完结简略,判别功率高
  • 缺点:很难处理目标之间的相互循环引证(objA.instance = objB; objB.instance = objA)的问题,所以java言语并没有选用引证计数法办理内存

根查找算法

为什么这11道JVM面试题这么重要(附答案)

Java和C#都是运用根查找算法来判别目标是否存活。经过一系列的名为“GC Root”的目标作为起始点,从这些节点开始向下查找,查找一切走过的途径称为引证链(Reference Chain),当一个目标到GC Root没有任何引证链相连时(用图论来说便是GC Root到这个目标不可达时),证明该目标是能够被收回的。

在Java中这些目标能够成为GC Root:

  • 虚拟机栈(栈帧中的本地变量表)中的引证目标
  • 办法区中的类静态特点引证的目标
  • 办法区中的常量引证目标
  • 本地办法栈中JNI(即Native办法)的引证目标

本文由传智教育博学谷狂野架构师教研团队发布。

假如本文对您有协助,欢迎关注点赞;假如您有任何主张也可留言评论私信,您的支持是我坚持创造的动力。

转载请注明出处!