自己整理总结的JVM《浅尝JVM》
本帖最后由 徐行且慢 于 2020-10-13 16:27 编辑jvm是一个可运行java代码的假想计算机。组成:
image.png
[*] 字节码指令集
[*] 一组寄存器
[*] 栈
[*] 垃圾回收
[*] 堆
[*] 存储方法域
jvm运行过程
image.png
java源文件通过编译器转为字节码文件
字节码文件通过jvm转化为机器码
每个平台解释不同,实现java代码的虚拟机是相同的,所以java能够跨越平台。
一个程序从开始运行,虚拟机就会开始实例化。多个程序启动就会存在多个虚拟机实例
程序如果关闭,虚拟机实例消亡。
多虚拟机之间的数据不能共享。
image.png
线程Hotspot VM
[*]/ˈhɑːtspɑːt /
[*]jvm当中的线程是指程序执行过程中的线程实体(执行一个方法就是线程)。JVM允许一个应用并发执行多个线程。
[*]JVM线程跟操作系统原生线程有直接映射关系。
[*]当线程本地存储,缓冲区分配、同步对象、栈、程序计数器等准备好,就会创建一个操作系统原生线程。
[*]JVM结束之后原生线程随之被回收。
[*]操作系统负责调度所有线程,并把他们分配到任何可用的CPU上。
[*]原生线程初始化完毕,就会执行方法(java线程的run方法)。
[*]线程结束时,会释放原生线程和java线程的所有资源。
映射是个术语,指两个元素的集之间元素相互“对应”的关系
虚拟机线程(VM thread):
[*] thread /θred/
这个线程等待JVM到达安全点操作出现。这些操作必须要在独立的线程里执行,因为当堆修改无法进行时,线程需要JVM位于安全点。
。这些独立的类型有:stop-the-world垃圾回收、线程栈dump、线程暂停、线程偏向锁(biased locking)解除。
stop-the-world垃圾回收
详见:Java垃圾回收中Stop-The-World和JVM中的Stop-The-World:
[*]Stop-The-World机制简称STW,是在执行垃圾收集算法时,Java应用程序的其他所有线程都被挂起(除了垃圾收集帮助器之外)。
[*]Java中一种全局暂停现象,全局停顿,所有Java代码停止,native代码可以执行,但不能与JVM交互;这些现象多半是由于gc引起。
线程偏向锁(biased locking)解除
Java偏向锁实现原理(Biased Locking)
biased 偏向
[*]/ˈbaɪəst
locking 锁定
[*] /'lɒkɪŋ/
周期性任务线程:
这个线程负责定时器事件(也就是中断),用来调度周期性操作的执行。
GC线程:
这些线程支持JVM中不同的垃圾回收活动。
编译器线程:
这些线程在运行时将字节码动态编译成本地平台相关的机器码。
信号分发线程:
这个线程接受发送到JVM的信号并调用适当的JVM方法处理。
JVM内存区域
file:///C:/Users/admingao/Documents/My%20Knowledge/temp/4eb3fcdb-5862-4930-9281-74cd40c44371/128/index_files/c84941ba1e4961ea3dbf03cff73816e9.png
JVM内存区域:
[*]私有区域:
[*]程序计数器
[*]虚拟机栈
[*]本地方法区
[*]线程共享区域: .
[*]java堆
[*]方法区
[*]直接内存
线程的生命周期
线程私有数据区域生命周期与线程相同,依赖用户线程的启动/结束 而 创建/销毁(在Hotspot VM内,每个线程都与操作系统的本地线程直接映射,因此这部分内存区域的存/否跟随本地线程生/死对应)
线程共享区域随虚拟机的启动/关闭而创建/销毁
直接内存
直接内存并不是JVM运行时数据区的一部分,但也会被频繁的使用:在JDK1.4引入的NIO提供了基于Channel与Buffer的IO方式。他可有使用Native函数库直接分配堆外内存,然后使用DirectByteBuffer对象作为这块内存的引用进行操作,这样避免了在Java堆和Native堆中的来回复制数据,因此在一些场景中可以显著提高性能。
线程私有区域
线程私有:Java虚拟机的多线程是通过线程轮流切换并分配处理器执行时间的方式来实现,也就是说,在同一时刻一个处理器内核只会执行一条线程,处理器切换线程时并不会记录上一个线程执行到哪个位置,所以为了线程切换后依然能恢复到原位,每条线程都需要有各自独立的程序计数器。程序计数器
程序计数器(Program Counter Register)是一块较小的内存空间,它可以看做是当前线程所执行的字节码的行号指示器。在虚拟机的概念模型里(仅是概念模型,各种虚拟机可能会通过一些更高效的方式去实现),字节码解释器工作时就是通过改变这个计数器的值来选取下一条需要执行的字节码指令,分支、循环、跳转、异常处理、线程恢复等基础功能都需要依赖这个计数器来完成
特点:
[*]一块较小的内存空间,是当前线程所执行的字节码的行号指示器,每条线程都要有一个独立的程序计数器,这类内存也称为“线程私有”的内存。
[*]正在执行java方法的话,计数器记录的是虚拟机字节码指令的地址(当前指令的地址)。如果还是Native方法,则为空。
[*]这个内存区域是唯一一个在虚拟机中没有规定任何OutOfMemoryError(内存溢出)情况的区域。
[*]程序计数器占用内存很小,在进行JVM内存计算时,可以忽略不计。
虚拟线程
是描述java方法执行的内存模型,每个方法在执行的同时都会创建一个栈帧(Stack Frame)用于存储局部变量表、操作数栈、动态链接、方法出口等信息。
file:///C:/Users/admingao/Documents/My%20Knowledge/temp/4eb3fcdb-5862-4930-9281-74cd40c44371/128/index_files/c0526727-303f-4da2-a485-4bb124eef53b.png
每个方法从调用到执行完成的过程,就对应着一个栈帧从虚拟机栈中入栈到出栈的过程。
file:///C:/Users/admingao/Documents/My%20Knowledge/temp/4eb3fcdb-5862-4930-9281-74cd40c44371/128/index_files/c8bd3af2-6e53-4259-aa08-de3c6c116798.jpg
java局部变量表:是栈帧重要组中部分之一。他主要保存函数的参数以及局部的变量信息。局部变量表中的变量作用域是当前调用的函数。函数调用结束后,随着函数栈帧的销毁。局部变量表也会随之销毁,释放空间。
操作数栈:操作数栈可理解为java虚拟机栈中的一个用于计算的临时数据存储区。
动态链接:部分符号引用在运行期间转化为直接引用,这种转化为动态链接
本地方法区(线程私有)
本地方法区和Java Stack作用类似,区别是虚拟机栈为执行Java方法服务,而本地方法栈则为Native方法服务,如果一个VM实现使用C-linkage模型来支持Native调用,那么该栈将会是一个C栈,但HotSpot VM直接就把本地方法栈和虚拟机栈合二为一。
支持一下最近也要开始看jvm哎 程序员界太卷了 图片挂了 看jvm总是觉得特别抽象,有什么好的办法吗
页:
[1]