JVM入门必备基础知识————-一篇文档足够了(记录自己学习的过程)

一:JVM基本概念

1、什么是JVM

  • VM的中文名称叫Java虚拟机,它是由软件技术模拟出计算机运行的一个虚拟的计算机。
  • JVM也充当着一个翻译官的角色,我们编写出的Java程序,是不能够被操作系统所直接识别的,而JVM负责把我们的程序翻译给系统“听”,告诉它我们的程序需要做什么操作。
  • Java的程序需要经过编译后,产生.Class文件,JVM才能识别并运行它。

2、JVM体系结构

JVM入门必备基础知识-------------一篇文档足够了(记录自己学习的过程)
加载:
  • 加载就是把类的.class文件读到内存中,并为之创建一个Java.lang.Class对象。
  • 类加载由类加载器完成,类加载器由JVM提供。被称为系统类加载器。
  • 使用不同的类加载器可以对不同来源的.class文件进行加载:
  1. 从本地文件系统加载.class文件

  2. 从JAR包加载class文件,这种方式也是很常见的。比如JDBC编程时用到的数据库驱动类就放在JAR文件中,JVM可以从JAR文件中直接加载该class文件。

  3. 通过网络加载class文件。

  4. 通过源文件动态编译并加载。

链接:

当类被加载之后,系统为之生成一个对应的Class对象,接着将会进入连接阶段,连接阶段负责把类的二进制数据合并到JRE中。类连接又可分为如下3个阶段。

验证:验证阶段用于检验被加载的类是否有正确的内部结构,并和其他类协调一致。验证阶段是Java非常重要的一个阶段,它会直接的保证应用是否会被恶意入侵的一道重要的防线,越是严谨的验证机制越安全。验证的目的在于确保Class文件的字节流中包含信息符合当前虚拟机要求,不会危害虚拟机自身安全。其主要包括四种验证,文件格式验证元数据验证字节码验证符号引用验证

准备:类准备阶段负责为类的静态变量分配内存,并设置默认初始值。

解析:负责将符合引用转为直接引用。

初始化:

初始化是为类的静态变量赋予正确的初始值。和准备阶段的区别在于:准备阶段是设置默认初始值。
例如: 首先将字节码文件加载到内存中,通过链接中的验证后到达准备阶段,这时候把 a 的值初始化为0, 然后经过解析,最后到初始化阶段,才会把真正的10赋给a。

6、类加载机制

知道了类加载过程,那么对于.class文件,java虚拟机如何才能按照class字节码中描述的内容进行运用和使用呢就需要类加载机制对其进行规范和约束,那我们就谈谈什么是类加载机制,以及类加载机制的方式和生命周期。

类加载机制:虚拟机把.class文件加载到内存中,并对其进行验证、解析、初始化,最终形成可以被虚拟机识别的java类型的过程。

说到这,我们脑海中可能会产生几个问题:

1. 虚拟机什么时候加载.Class文件呢类加载时机)
2. 它又是怎么加载的呢类加载器、双亲委派机制)
3. 经历了怎样的步骤呢类加载过程与步骤)

下面我们所讲的就是围绕这三个问题来。

1)类加载时机

在上面的第五模块,已经讲了类加载过程,类加载过程有七个阶段,第一个阶段就是加载,那么什么时候虚拟机开始把.class文件加载到内存中去呢就需要了解一下类加载时机。

Java虚拟机规范中并没有进行强制约束,这点可以交给虚拟机的具体实现来自由把握。但是对于初始化阶段,虚拟机规范则是严格规定了有且只有5种情况必须立即对类进行“初始化”(而加载、验证、准备自然需要在此之前开始),具体5种情况如下图所示:

JVM入门必备基础知识-------------一篇文档足够了(记录自己学习的过程)

这是运行结果,由结果可以看到,子类Son并没有被初始化。这是为什么呢strong>这是因为对于静态字段,只有直接定义这个字段的类才会被初始化,因此通过其子类来引用父类中定义的静态字段,只会触发父类的初始化而不会触发子类的初始化。
上面的例子中,由于count字段是在Father类中定义的,因此该类会被初始化,此外,在初始化类Father的时候,虚拟机发现其父类Grandpa还没被初始化,因此虚拟机将先初始化其父类Grandpa,然后初始化子类Father,而Son始终不会被初始化.

JVM入门必备基础知识-------------一篇文档足够了(记录自己学习的过程)
  1. 类加载器负责加载所有的类,其为所有被载入内存中的类生成一个java.lang.Class实例对象。

  2. 一旦一个类被加载如JVM中,同一个类就不会被再次载入了。

  3. 在JVM中,一个类用其全限定类名和其类加载器作为其唯一标识。

JVM预定义有三种类加载器,当一个 JVM启动的时候,Java开始使用如下三种类加载器:

a)引导类加载器((bootstrap class loader):
  • 它用来加载 Java 的核心类,是用原生代码来实现的,并不继承自 java.lang.ClassLoader。
  • 由于引导类加载器涉及到虚拟机本地实现细节,开发者无法直接获取到启动类加载器的引用,所以不允许直接通过引用进行操作。

下面程序可以获得根类加载器所加载的核心类库,并会看到本机安装的Java环境变量指定的jdk中提供的核心jar包路径:

JVM入门必备基础知识-------------一篇文档足够了(记录自己学习的过程)

双亲委派机制工作原理

1-类加载器收到类加载的请求;

2-把这个请求委托给父加载器去完成,一直向上委托,直到启动类加载器;

3-启动器加载器检查能不能加载(使用findClass()方法),能就加载(结束);否则,抛出异常,通知子加载器进行加载。

4-重复步骤三;

双亲委派机制的优势

  1. Java类随着它的类加载器一起具备了一种带有优先级的层次关系,通过这种层级关可以避免类的重复加载。

  2. java核心api中定义类型不会被随意替换,假设通过网络传递一个名为java.lang.Integer的类,通过双亲委托模式传递到启动类加载器,而启动类加载器在核心Java API发现这个名字的类,发现该类已被加载,并不会重新加载网络传递的过来的java.lang.Integer,而直接返回已加载过的Integer.class,这样便可以防止核心API库被随意篡改。

文章知识点与官方知识档案匹配,可进一步学习相关知识Java技能树首页概览91528 人正在系统学习中

来源:编程初体验

声明:本站部分文章及图片转载于互联网,内容版权归原作者所有,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!

上一篇 2019年8月16日
下一篇 2019年8月17日

相关推荐