一篇帮你搞定JVM基本概念(超详细)
Posted adventure.Li
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了一篇帮你搞定JVM基本概念(超详细)相关的知识,希望对你有一定的参考价值。
一、整体框架
二、核心知识学习
- 基本概念
(1)定义
JVM:Java virtual machine,即Java虚拟机;是可运行Java代码的假想计算机,包括一套
指令集
、一组寄存器
、一个栈
、一个垃圾回收、堆
和一个存储方法域
。JVM运行OS之上,它与硬件没有直接的交互
。
(2)运行过程
Java源文件
通过编译器,产生相应的class文件
(即字节码文件,也是由此 出现 一次编译到处运行的说法 跨平台的特性
),再通过JVM中的解释器,编译成特定的机器码
。
- 线程
线程: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方法处理。
- 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)方法区/永久代
用于存储被加载的类信息、常量、静态变量、即时编译器编译的代码等数据。 主要针对常量池的回收和类型的卸载。
运行时常量池
是方法区的主要部分。
- 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基本概念(超详细)的主要内容,如果未能解决你的问题,请参考以下文章
看完这篇总结,你会发现其实spring面试真的没那么难,一篇帮你彻底搞定spring。