一篇帮你搞定JVM基本概念(超详细)

Posted adventure.Li

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了一篇帮你搞定JVM基本概念(超详细)相关的知识,希望对你有一定的参考价值。

一、整体框架

在这里插入图片描述

二、核心知识学习

  1. 基本概念

(1)定义

JVM:Java virtual machine,即Java虚拟机;是可运行Java代码的假想计算机,包括一套 指令集、一组 寄存器、一个、一个垃圾回收、和一个存储方法域。JVM运行OS之上,它与硬件没有直接的交互

(2)运行过程

Java源文件 通过编译器,产生相应的class文件(即字节码文件,也是由此 出现 一次编译到处运行的说法 跨平台的特性),再通过JVM中的解释器,编译成特定的机器码

在这里插入图片描述

  1. 线程

线程:CPU资源分配的基本单位;进程计算机资源(包括内存、CPU等)的分配基本单位。程序(数据+指令)

进程是资源(CPU、内存等)分配的基本单位,它是程序执行时的一个实例,即运行中的程序。
程序是存储在磁盘上, 包含可执行机器指令和数据的静态实体。 即进程或者任务是处于活动状态的计算机程序。
三者详细对比

在JVM中,Java线程与OS线程有直接映射关系。当线程本地存储、缓冲区分配、同步对象、栈、PC等准备好之后就会创建一个OS原生的线程,当原生线程初始化完毕,则启动Java线程的run方法。Java线程结束,原生OS的线程也随之结束。

JVM后台运行的线程:
a.虚拟机线程:这种线程的操作是需要JVM达到安全点才会出现。这些操作必须在不同的线程中发生的原因是他们都需要JVM达到安全点,这样堆才不会变化。这种线程的执行类型包括"stop-the-world"的垃圾收集,线程栈收集,线程挂起以及偏向锁撤销。
b.周期性任务线程:负责中断,调度周期性操作的执行。
c.GC 线程:垃圾回收活动。
d.编译器线程:将字节码动态编译成本地平台相关的机器码。
e.信号分发线程:接收发送到JVM的信号并调用相应JVM方法处理。

  1. JVM内存区域

在这里插入图片描述

JVM内存内存区域主要分为 私有线程区域(PC、虚拟机栈、本地方法栈)、共享区域(方法区、堆)、直接内存。

线程私有区域:生命周期与线程相同,依赖用户的启动与销毁。
线程共享区域:随虚拟机的启动/关闭而创建/销毁。
直接内存:并不是JVM运行时数据区的一部分,但频繁使用,JDK1.4引入的NIO提出基于 Channel与Buffer的IO方式,基于此,可以使用本地函数库(原生底层API)直接分配堆外内存。

(1)PC(程序计数器)

一块较小的内存空间, 是当前线程所执行字节码的行号的指示器。每一个线程都有一个独立的PC。
若执行Java方法,PC记录的是字节码指令的地址,若是Native方法,则为空。
唯一一块JVM没有规定OutOfMemoryError的区域。

(2)虚拟机栈

在这里插入图片描述

描述Java方法执行的内存模型,每个方法在执行的同时都会创建一个栈帧(存数据和部分过程结构的数据结构,同时用来动态链接(上图未写到)和异常分派,随方法调用创建,随方法结束而摧毁)。

(3)本地方法栈

和JVM Stack类似,区别在于JVM stack为Java方法服务,而本地方法栈为native方法服务。

(4)堆

被线程共享的一块内存区域。
堆(线程共享):对象、对象的全局变量、数组
栈(线程私有):声明为局部变量的 基本数据类型、对象引用(是引用,不是对象本身)、方法参数),

因此也能理解为什么死循环创建对象是报错 heap
在这里插入图片描述

(5)方法区/永久代

用于存储被加载的类信息、常量、静态变量、即时编译器编译的代码等数据。 主要针对常量池的回收和类型的卸载。运行时常量池是方法区的主要部分。

在这里插入图片描述

  1. JVM运行时内存

Java堆 从GC的角度还可以细分为: 新生代(Eden区,From Survivor区和To Survivor区)以及老年代。

(1)新生代

用来存放新生的对象,一般占据 堆的1/3 空间。由于频繁创建新对象,会触发MinorGC进行垃圾回收。

a.Eden区(占据新生代的8/10)
Java新对象(new Object()) 的出生地,当新创建的内存过大时,直接分配到老年代。当Eden区不够则触发MinorGC,对新生代进行一次回收。

b.ServivorFrom
上一次GC幸存者,作为这次的GC的被扫描者。

c.ServivorTo
保留了一次MinorGC过程的幸存者。

(2)MinorGC的过程(复制-> 清空->互换,复制算法)

a.Eden、servivorFrom复制到ServivorTO,年龄+1

将servivorFrom的存活对象复制到ServivorTo区域(若达到老年的标准,则复杂度老年代),同时把这些对象的年龄+1(如果servivorTo不够用就放到老年代)

b.清空Eden、ServivorFrom的对象

c.ServivorTo和ServivorFrom互换。

(3)老年代

主要存放应用程序中生命周期长的内存对象。
MajorGC采用标记清楚算法进行回收:
当老年代装不下时报错OOM(Out of Memory)

(4)永久代

指内存的永久保存区域,主要存放Class和Meta(元数据),Class被加载存在永久区(方法区,回顾内存区域部分),与实例的存储位置不一样(堆)。GC不会再主程序运行时对永久区进行清理,当Class加载过多则会抛出OOM的异常。

以上是关于一篇帮你搞定JVM基本概念(超详细)的主要内容,如果未能解决你的问题,请参考以下文章

深度分析:Java中如何如理异常,一篇帮你搞定!

深度分析:Java中如何如理异常,一篇帮你搞定!

看完这篇总结,你会发现其实spring面试真的没那么难,一篇帮你彻底搞定spring。

看完这篇总结,你会发现其实spring面试真的没那么难,一篇帮你彻底搞定spring。

面试被问如何保证缓存与数据库的双写一致性?这篇帮你搞定

超详细干货收藏向Java面试必备一文搞定Java集合容器