JVM总体概述

JDK(Java Development Kit) 是 Java 语言的软件开发工具包(SDK)。JDK 物理存在,是 programming toolsJREJVM 的一个集合。

JRE

JRE(Java Runtime Environment)Java 运行时环境,JRE 是物理存在的,主要由Java APIJVM 组成,提供了用于执行 java 应用程序最低要求的环境。

JVM

JVM是一种用于计算设备的规范,它是一个虚构的计算机的软件实现,简单的说,JVM是运行byte code字节码程序的一个容器。

JVM的特点

  • 基于堆栈的虚拟机:最流行的计算机体系结构,如英特尔 X86 架构和 ARM 架构上运行基于 寄存器。比如,安卓的 Davilk 虚拟机就是基于 寄存器 结构,而 JVM 是基于栈结构的。

  • 符号引用 :除了基本类型以外的数据 (类和接口) 都是通过符号来引用,而不是通过显式地使用内存地址来引用。

  • 垃圾收集 :一个类的实例是由用户程序创建和垃圾回收自动销毁

  • 网络字节顺序Java class文件用网络字节码顺序来进行存储,保证了小端的Intel x86架构和大端的RISC系列的架构之间的无关性。

JVM字节码

JVM使用Java字节码的方式,作为Java 用户语言机器语言 之间的中间语言。实现一个通用的机器无关 的执行平台。

JVM能干什么


基于安全方面考虑,JVM 要求在 class 文件中使用强制性的语法和约束,但任意一门语言都可以转换为被 JVM 接受的有效的 class 文件。作为一个通用的、机器无关的执行平台,任何其他语言的实现者都可将 JVM 当作他的语言产品交付媒介。

JVM 中执行过程如下:

  • 加载代码

  • 验证代码

  • 执行代码

  • 提供运行环境

JVM生命周期


  • 启动:任何一个拥有main方法的class都可以作为JVM实例运行的起点。

  • 运行main函数为起点,程序中的其他线程均有它启动,包括daemon守护线程和non-daemon普通线程。daemonJVM自己使用的线程比如GC线程,main方法的初始线程是non-daemon

  • 消亡:所有线程终止时,JVM实例结束生命。

JVM组成架构


JAVA 代码执行过程如下:

1. 类加载器(Class Loader)

类加载器 负责加载程序中的类型(类和接口),并赋予唯一的名字予以标识。

JDK 默认提供的三种 ClassLoader如下:

类加载器的关系

  1. Bootstrap Classloader 是在Java虚拟机启动后初始化的。

  2. Bootstrap Classloader 负责加载 ExtClassLoader,并且将 ExtClassLoader的父加载器设置为 Bootstrap Classloader

  3. Bootstrap Classloader 加载完 ExtClassLoader 后,就会加载 AppClassLoader,并且将 AppClassLoader 的父加载器指定为 ExtClassLoader

类加载器的作用

| Class Loader | 实现 | 负责加载 |

| — | — | — |

| Bootstrap Loader | C++ | %JAVA_HOME%/jre/lib, %JAVA_HOME%/jre/classes以及-Xbootclasspath参数指定的路径以及中的类 |

| Extension ClassLoader | Java | %JAVA_HOME%/jre/lib/ext,路径下的所有classes目录以及java.ext.dirs系统变量指定的路径中类库 |

| Application ClassLoader | Java | Classpath所指定的位置的类或者是jar文档,它也是Java程序默认的类加载器 |

双亲委托机制

JavaClassLoader的加载采用了双亲委托机制,采用双亲委托机制加载类的时候采用如下的几个步骤:

  1. 当前ClassLoader首先从自己已经加载的类中查询是否此类已经加载,如果已经加载则直接返回原来已经加载的类。

  2. 当前ClassLoader的缓存中没有找到被加载的类的时候,委托父类加载器去加载,父类加载器采用同样的策略,首先查看自己的缓存,然后委托父类的父类去加载,一直到Bootstrap ClassLoader

  3. 当所有的父类加载器都没有加载的时候,再由当前的类加载器加载,并将其放入它自己的缓存中,以便下次有加载请求的时候直接返回。

小结 :双亲委托机制的核心思想分为两个步骤。其一,自底向上检查类是否已经加载;其二,自顶向下尝试加载类。

ClassLoader隔离问题

每个类装载器都有一个自己的命名空间用来保存已装载的类。当一个类装载器装载一个类时,它会通过保存在命名空间里的类全局限定名(Fully Qualified Class Name)进行搜索来检测这个类是否已经被加载了。

JVMDalvik 对类唯一的识别是 ClassLoader id + PackageName + ClassName,所以一个运行程序中是有可能存在两个包名和类名完全一致的类的。并且如果这两个”类”不是由一个 ClassLoader 加载,是无法将一个类的示例强转为另外一个类的,这就是 ClassLoader 隔离。

双亲委托ClassLoader类一致问题的一种解决方案,也是 Android 差价化开发和热修复的基础。

类装载器特点

Java提供了动态加载特性。在运行时的第一次引用到一个class的时候会对它进行装载(Loading) 、** 链接(Linking)** 和 ** 初始化(Initialization) ** ,而不是在编译时进行。不同的JVM的实现不同,本文所描述的内容均只限于Hotspot JVM

JVM的类装载器负责动态装载,Java的类装载器有如下几个特点:

  • 层级结构:Java里的类装载器被组织成了有父子关系的层级结构。Bootstrap类装载器是所有装载器的父亲。

  • 代理模式: 基于层级结构,类的代理可以在装载器之间进行代理。当装载器装载一个类时,首先会检查它在父装载器中是否进行了装载。如果上层装载器已经装载了这个类,这个类会被直接使用。反之,类装载器会请求装载这个类

  • 可见性限制:一个子装载器可以查找父装载器中的类,但是一个父装载器不能查找子装载器里的类。

  • 不允许卸载:类装载器可以装载一个类但是不可以卸载它,不过可以删除当前的类装载器,然后创建一个新的类装载器装载。

类装载器过程

  • 加载(Loading)

    首先,根据类的全限定名找到代表这个类的Class文件,然后读取到一个字节数组中。接着,这些字节会被解析检验它们是否代表一个Class对象 并包含正确的majorminor版本信息。直接父类 的类和接口也会被加载进来。这些操作一旦完成,类或者接口对象 就从二进制表示中创建出来了。

  • 链接(Linking)

    链接是检验类或接口并准备类型和父类接口的过程。链接过程包含三步:校验(Verifying)准备(Preparing)部分解析(Optionally resolving)

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-glgZgksp-1630058694960)(https://user-gold-cdn.xitu.io/2018/7/17/164a8528dd507f0a?imageView2/0/w/1280/h/960/format/webp/ignore-error/1)]

    • 验证

    这是类装载中最复杂的过程,并且花费的时间也是最长的。任务是确保导入类型的准确性,验证阶段做的检查,运行时不需要再做。虽然减慢加了载速度,但是避免了多次检查。

    • 准备

    准备过程通常分配一个结构用来存储类信息,这个结构中包含了类中定义的成员变量方法接口信息等。

    • 解析

    解析是可选阶段,把这个类的常量池中的所有的符号引用改变成直接引用。如果不执行,符号解析要等到字节码指令使用这个引用时才会进行。

  • 初始化(Initialization)

把类中的变量初始化成合适的值。执行静态初始化程序,把静态变量初始化成指定的值。

JVM规范定义了上面的几个任务,不过它允许具体执行的时候能够有些灵活的变动。

2. 执行引擎(Execution Engine)

通过类装载器装载的,被分配到JVM运行时数据区的字节码会被执行引擎执行。

中的所有的符号引用改变成直接引用。如果不执行,符号解析要等到字节码指令使用这个引用时才会进行。

  • 初始化(Initialization)

把类中的变量初始化成合适的值。执行静态初始化程序,把静态变量初始化成指定的值。

JVM规范定义了上面的几个任务,不过它允许具体执行的时候能够有些灵活的变动。

2. 执行引擎(Execution Engine)

通过类装载器装载的,被分配到JVM运行时数据区的字节码会被执行引擎执行。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值