JVM模型

一.JVM模型

JVM模型分为类加载子系统【1】、运行时数据、执行引擎(内有垃圾回收器)、本地库接口(JNI Java Native Interface)
JVM内存模型是指运行时数据区的模型,因为运行时数据区又称为内存区(还有注意区分Java内存模型
在这里插入图片描述

二.运行时数据区(Runtime Data Area)详解

1.VM Stack(虚拟机栈)(virtual machine stack)
  1. 线程私有,生命周期与线程一致、会抛出StackOverflowError和OutOfMemoryError异常。
  2. 描述的是Java方法执行的内存模型,每个方法在执行的同时都会创建一个栈帧(Stack Frame)用于存储局部变量表,操作数栈,动态链接,方法出口等信息。
    2.1. 局部变量表(Local Variable Table):(1)存储八大基本数据类型,(2)对象引用(指针或者句柄),(3)returnAddress类型(指向一条字节码指令的地址)
    2.2. 操作数栈(Operand Stack) :也称作操作栈,是一个后入先出栈(LIFO)。数据来源:局部变量表、对象实例.
    2.3. 动态链接(Dynamic Linking):Java虚拟机栈中,每个栈帧都包含一个指向运行时常量池中该栈所属方法的符号引用【2】,持有这个引用的目的是为了支持方法调用过程中的动态链接.
    2.4. 方法返回(Return Adress):无论方法是否正常完成,都需要返回到方法被调用的位置,程序才能继续进行。
  3. StackOverflowError异常: jvm规定了栈的最大深度,当执行时栈的深度大于了规定的深度,就会抛出StackOverflowError错误。(有栈才会有这个异常)
  4. 如果虚拟机在扩展栈时无法申请到足够的内存空间,则抛出 OutOfMemoryError 异常.
2.Native Methed Stack(本地方法栈)
  1. 于VS Stack几乎一致
  2. 会抛出StackOverflowError和OutOfMemoryError异常。
3.Method Area(方法区)(Non-Heap)
  1. 线程共享、可垃圾回收GC(比堆难)、内存不连续、可拓展、会抛出OutOfMemoryError异常.
  2. 常量池在方法区内.
  3. 存储信息:类信息、常量、静态变量、计时编译器编译后的代码。
    类信息包括:
    1. 类型的全名(The fully qualifiedname of the type)
    2. 类型的父类型全名(除非没有父类型,或者父类型是java.lang.Object)(The fully qualified name of the typeís direct superclass)
    3. 该类型是一个类还是接口(class or an interface)(Whether or not the type is a class )
    4. 类型的修饰符(public,private,protected,static,final,volatile,transient等)(The typeís modifiers)
    5. 所有父接口全名的列表(An ordered list of the fully qualified names of any direct superinterfaces)
    6. 类型的字段信息(Field information)
    7. 类型的方法信息(Method information)
    8. 所有静态类变量(非常量)信息(All class (static) variables declared in the type, except constants)
    9. 一个指向类加载器的引用(A reference to class ClassLoader)
    10. 一个指向Class类的引用(A reference to classClass)
    11. 基本类型的常量池(The constant pool for the type)
4.Heap(堆)
  1. 线程共享、可垃圾回收GC(最大的GC回收处,所以堆又称为’GC堆’)、内存不连续、可拓展、会抛出OutOfMemoryError异常.
  2. 内存最大.
  3. 存储类型:先进先出.
  4. 存储数据类型:对象的实例.
5.Program Counter Registrer(程序计数器)
  1. 唯一一个不会抛出OutOfMemoryError异常.但内存小。
  2. 线程私有(一个线程一个程序计数器、各条线程之间的计数器互不影响,独立存储【3】)
  3. 字节码解释器工作时就是通过改变计数器的值来选取下一条字节码指令

三.ClassLoader(类加载器)详解

1.类加载器分三类:

(1)BootStrap classLoader(根类加载器、引导类加载器)
(2)Extentions classLoader(扩展类加载器)
(3)App classLoader(又称System classLoader)(系统类加载器)

2.类加载过程

类加载过程

  1. 加载:将类的class文件读入到内存,并为之创建一个java.lang.Class对象.
  2. 链接
    (1)验证:验证阶段用于检验被加载的类是否有正确的内部结构,并和其他类协调一致(文件格式验证,元数据验证,字节码验证,符号引用验证)
    (2)准备:类准备阶段负责为类的静态变量分配内存,并设置默认初始值
    (3)解析:将类的二进制数据中的符号引用替换成直接引用
  3. 初始化是为类的静态变量赋予正确的初始值【4】
    在这里插入图片描述
3.类加载机制【5】

双亲委派:父类先加载,找不到在分配给子类加载,依次往下,找到了就返回结果,都没找到抛出异常.(自定义加载器不定义父类默认AppClassLoader)
双亲委派机制优势:避免了重复加载类。

-注意:这个查找顺序 ,其实并不是从父类开始,只是查找***目标路径***从父类开始 (找不到按箭头执行,找到了就返回结果)
自定义加载器(缓存中找)–> AppClassLoader(缓存中查找)–>ExtClassLoader(缓存中查找)–>BootStrapClassLoader(缓存中查找)----->在BootstrapClassLoader规定路径寻找(sun.boot.class.path)–>在ExtClassLoader规定路径寻找(java.ext.dirs)–>在AppClassLoader规定路径寻找(Java.ext.dirs)–>在自定义的类加载器指定路径找(没有就没了)
图解来源


tips:

  1. 在JVM中内存一共有3种:Heap(堆内存),Non-Heap(非堆内存)和Native(本地内存)。
  2. GC回收算法(下一篇具体介绍)
  3. ExtClassLoader的父类是BootStrapClassLoader,可是Java中用反射方法.getClassLoader().getParent().toString()获取不到,返回为空指针异常,因为ExtClassLoader在Java中压根没有父类加载器,原因是:BootStrapClassLoader是C/C++编写的,Java调不到,想要调用方法:-------------当ExtClassLoader的父类为null---->运行BootStrapClassLoader------所以说虽然BootStrapClassLoader是ExtClassLoader的父类加载器,不过在Java中继承不到.

【1】类加载子系统
  1. 类加载子系统也可以称之为类加载器,JVM默认提供三个类加载器:
    (1)BootStrap ClassLoader :称之为启动类加载器,是最顶层的类加载器,负责加载JDK中的核心类库,如 rt.jar、resources.jar、charsets.jar等。
    (2)Extension ClassLoader:称之为扩展类加载器,负责加载Java的扩展类库,默认加载$JAVA_HOME中jre/lib/*.jar 或 -Djava.ext.dirs指定目录下的jar包。
    (3)App ClassLoader:称之为系统类加载器,负责加载应用程序classpath目录下所有jar和class文件。
    除了Java默认提供的三个ClassLoader(加载器)之外,我们还可以根据自身需要自定义ClassLoader,自定义ClassLoader必须继承java.lang.ClassLoader 类。除了BootStrap ClassLoader 之外的另外两个默认加载器都是继承自java.lang.ClassLoader。BootStrap ClassLoader 不是一个普通的Java类,它底层由C++编写,已嵌入到了JVM的内核当中,当JVM启动后,BootStrap ClassLoader 也随之启动,负责加载完核心类库后,并构造Extension ClassLoader 和App ClassLoader 类加载器。
  2. 类加载器子系统不仅仅负责定位并加载类文件,它还严格按照以下步骤做了很多事情:
    1. 加载:寻找并导入Class文件的二进制信息
    2. 连接:进行验证、准备和解析
      1)验证:确保导入类型的正确性
      2)准备:为类型分配内存并初始化为默认值
      3)解析:将字符引用解析为直接引用
    3. 初始化:调用Java代码,初始化类变量为指定初始值
【2】符号引用和直接引用

符号引用:以一组符号来描述所引用的目标,符号可以是任何形式的字面量,只要使用时能够无歧义的定位到目标即可.
直接引用可以是:

  1. 直接指向目标的指针。(网上多数理解为:指向对象,类变量和类方法的指针)
  2. 相对偏移量。 (指向实例的变量,方法的指针)
  3. 一个间接定位到对象的句柄。
    个人理解:其实总结下来就是符号引用其实是用不规则的方式定义到目标,而直接引用是用计算机规定的方式定位到目标(用指针或句柄的方式).
【3】虚拟机多线程实现原理
  1. Java虚拟机的多线程是通过线程轮流切换并分配处理器执行时间的方式来实现的,在任何一个确定的时刻,一个处理器(对于多核处理器来说是一个内核)只会执行一条线程中的指令。因此,为了线程切换后能恢复到正确的执行位置,每条线程都需要有一个独立的程序计数器,各条线程之间的计数器互不影响,独立存储,我们称这类内存区域为“线程私有”的内存。
    如果线程正在执行的是一个Java方法,这个计数器记录的是正在执行的虚拟机字节码指令的地址;如果正在执行的是Natvie方法,这个计数器值则为空(Undefined)。
【4】这里可能觉得和链接里的准备有点冲突,其实不然

比如说类中定义 private static int a = 1;准备阶段是给他赋了默认值0,即int这是时候是 private static int a =0;----->在初始化阶段给a赋值10,即----->private static int a = 10;

【5】JVM的类加载机制3种
  1. 全盘负责:所谓全盘负责,就是当一个类加载器负责加载某个Class时,该Class所依赖和引用其他Class也将由该类加载器负责载入,除非显示使用另外一个类加载器来载入。
  2. 双亲委派:所谓的双亲委派,则是先让父类加载器试图加载该Class,只有在父类加载器无法加载该类时才尝试从自己的类路径中加载该类。通俗的讲,就是某个特定的类加载器在接到加载类的请求时,首先将加载任务委托给父加载器,依次递归,如果父加载器可以完成类加载任务,就成功返回;只有父加载器无法完成此加载任务时,才自己去加载。
  3. 缓存机制。缓存机制将会保证所有加载过的Class都会被缓存,当程序中需要使用某个Class时,类加载器先从缓存区中搜寻该Class,只有当缓存区中不存在该Class对象时,系统才会读取该类对应的二进制数据,并将其转换成Class对象,存入缓冲区中。这就是为很么修改了Class后,必须重新启动JVM,程序所做的修改才会生效的原因。
阅读终点,创作起航,您可以撰写心得或摘录文章要点写篇博文。去创作
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
为什么要学JVM1、一切JAVA代码都运行在JVM之上,只有深入理解虚拟机才能写出更强大的代码,解决更深层次的问题。2、JVM是迈向高级工程师、架构师的必备技能,也是高薪、高职位的不二选择。3、同时,JVM又是各大软件公司笔试、面试的重中之重,据统计,头部的30家互利网公司,均将JVM作为笔试面试的内容之一。4、JVM内容庞大、并且复杂难学,通过视频学习是最快速的学习手段。课程介绍本课程包含11个大章节,总计102课时,无论是笔试、面试,还是日常工作,可以让您游刃有余。第1章 基础入门,从JVM是什么开始讲起,理解JDK、JRE、JVM的关系,java的编译流程和执行流程,让您轻松入门。第2章 字节码文件,深入剖析字节码文件的全部组成结构,以及javap和jbe可视化反解析工具的使用。第3章 类的加载、解释、编译,本章节带你深入理解类加载器的分类、范围、双亲委托策略,自己手写类加载器,理解字节码解释器、即时编译器、混合模式、热点代码检测、分层编译等核心知识。第4章 内存模型,本章节涵盖JVM内存模型的全部内容,程序计数器、虚拟机栈、本地方法栈、方法区、永久代、元空间等全部内容。第5章 对象模型,本章节带你深入理解对象的创建过程、内存分配的方法、让你不再稀里糊涂。第6章 GC基础,本章节是垃圾回收的入门章节,带你了解GC回收的标准是什么,什么是可达性分析、安全点、安全区,四种引用类型的使用和区别等等。第7章 GC算法与收集器,本章节是垃圾回收的重点,掌握各种垃圾回收算法,分代收集策略,7种垃圾回收器的原理和使用,垃圾回收器的组合及分代收集等。第8章 GC日志详解,各种垃圾回收器的日志都是不同的,怎么样读懂各种垃圾回收日志就是本章节的内容。第9章 性能监控与故障排除,本章节实战学习jcmd、jmx、jconsul、jvisualvm、JMC、jps、jstatd、jmap、jstack、jinfo、jprofile、jhat总计12种性能监控和故障排查工具的使用。第10章 阿里巴巴Arthas在线诊断工具,这是一个特别小惊喜,教您怎样使用当前最火热的arthas调优工具,在线诊断各种JVM问题。第11章 故障排除,本章会使用实际案例讲解单点故障、高并发和垃圾回收导致的CPU过高的问题,怎样排查和解决它们。课程资料课程附带配套项目源码2个159页高清PDF理论篇课件1份89页高清PDF实战篇课件1份Unsafe源码PDF课件1份class_stats字段说明PDF文件1份jcmd Thread.print解析说明文件1份JProfiler内存工具说明文件1份字节码可视化解析工具1份GC日志可视化工具1份命令行工具cmder 1份学习方法理论篇部分推荐每天学习2课时,可以在公交地铁上用手机进行学习。实战篇部分推荐对照视频,使用配套源码,一边练习一遍学习。课程内容较多,不要一次性学太多,而是要循序渐进,坚持学习。      
JVMJava虚拟机)结构模型JVM内存模型JVM的两个重要方面,可以简单理解为JVM的组成部分和内存管理机制。 JVM结构模型是指Java程序在运行时的执行环境,包括JVM的组成部分和它们的工作原理。JVM的主要组成部分包括类加载器、解释器、即时编译器、垃圾回收器和执行引擎。类加载器负责将Java类加载到JVM中,并将其转换为可执行代码;解释器负责解释字节码并执行相应的指令;即时编译器则将频繁执行的代码编译成本地机器码,以提高程序的执行效率;垃圾回收器则负责回收程序运行时不再使用的内存;执行引擎则负责执行程序的指令并输出结果。 JVM内存模型是指Java虚拟机管理程序运行时内存的方式,包括内存划分、内存分配和对象回收等机制。JVM内存模型规定了Java程序运行时内存的分配和管理方式。JVM内存模型将内存划分为不同的区域,包括方法区、堆、虚拟机栈、本地方法栈和程序计数器。其中,堆是Java程序运行时内存中最大的区域,用于存储对象实例。虚拟机栈和本地方法栈则用于存储程序执行时的局部变量和方法调用信息。方法区用于存储已加载的类信息、常量池、静态变量等数据。程序计数器则用于记录当前线程所执行的字节码指令位置。 总之,JVM结构模型JVM内存模型Java程序运行时的两个重要方面,了解和掌握它们的工作原理对于编写高效、稳定的Java程序至关重要。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Watson X

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值