一、JVM概述
1.简述JVM,JRE,JDK
- JVM:
- java虚拟机,java运行的环境,是一个虚构出来的计算机,是通过实际的计算机模拟仿真各个功能的来实现的,
- 对于java用户来说,他可以运行.class文件,
- java虚拟机在执行字节码时,把字节码解释成具体平台上的机器来执行命令
- 这也就是java能够"一次编译,到处运行的原因"
- JRE:
- 包含JVM标准实现和java核心类库
- JRE是java的运行环境,并不是java的开发环境,JRE中并不包含编译器和调试器
- 我们编写的java程序必须要有JRE才能运行
- JDK:
- 整个java的核心,包括了java的运行环境,java工具(编译器等),还有java基础的类库
- 总的来说JDK是用于java程序的开发,而JRE则是只能运行class而没有编译的功能。
2.JVM,JRE,JDK的联系
- 联系
- JVM不能单独搞定.class的执行,
- 解释.class文件的时候JVM需要调用解释所需要的类库lib
- 而类库lib就存在JDK下面的JRE中,JRE共俩个目录,一个是bin一个是lib,此bin就可以理解为JVM
- 总的来说,我们利用JDK开发后的java程序,通过JDK中的javac将我们的java文件编译成java字节码,JRE在运行这些字节码,JVM在解析这些字节码,映射在CPU中
3.JVM的特点
- 一次编译,到处运行(java语言跨平台性的主要原因)
- 自动内存管理
- 自动垃圾回收功能
4.JVM的组成
- 1.类加载区
- 2.运行时数据区
- 3.执行引擎
- 4.本地库接口
5.JVM的组成的用途
- 程序运行之前需要将java代码转换为字节码(class文件)
- JVM需要通过类加载器件文件加载在内存中的运行时数据区,
- 而字节码时jvm的一套指令规范,并不能直接交给底层操作系统去执行,所以需要特定的命令解析器执行引擎,将字节码编译成底层系统指令再交给CPU去执行,
- 而这个过程需要调用其他语言的接口本地库接口来实现整个程序的功能
二、类加载
1.类加载子系统的作用
- 类加载器子系统负责从文件系统或者网络中加载class文件,
- classLoader只负责class文件的加载,至于是否可以运行则由ExecutionEngine决定
- 加载的类信息存放于一块成为方法区的内存空间.
- 除了类的信息外,方法区中还会存放运行时常量池信息,可能还包括字符串字面量和数字常量
2.类加载Class Loader的角色
- class file存在于硬盘上,相当于一个模板,在执行时要加载到JVM当中,根据这个模板可以实例化n和一模一样的示例
- class file加载到JVM中,被称为DNA元数据模板,放在方法区中
- 实例化的最终成为元数据模板,这个过程需要一个运输工具(类加载器Class Loader)扮演一个快递员的角色
3.类加载的过程
- 加载:
- 通过类名(地址)获得此类的二进制字节流
- 将此字节流转换为方法区(原空间)的运行时结构
- 在内存中生成一个代表此类的java.lang.Class对象,作为方法区这个类的各种数据的访问入口
- 链接:
- 验证:
- 检验被加载的类是否有正确的内部结构,并和其他类是否协调一致
- 准备:
- 准备阶段则负责为类的静态属性分配内存,并设置默认初始值
- 解析:
- 将类的二进制数据中的符号引用替换成直接引用
- 验证:
- 初始化
- 对 static 修饰的变量或语句块进行赋值. 如果同时包含多个静态变量和静态代码块,则按照自上而下的顺序依次执行。
- 如果初始化一个类的时候,其父类尚未初始化,则优先初始化其父类。
- 顺序是:父类 static –> 子类 static –> 父类构造方法- -> 子类构造方法
4.类加载器分类
- 分为引导类加载器,自定义类加载器
5.双亲委派机制
- java虚拟机对class文件采用的是按需加载的方式,
- 需要该类的时候才会将它的class文件加载到内存中生成class对象
- 而加载某个类的class文件时,java虚拟机采用的是双亲委派模式,将请求交由父亲处理
- 工作原理
- 1.如果一个类加载器收到类加载请求,它并不会自己先去加载,而是把这个请求委托给父类的加载器去执行
- 2.如果父类加载器还存在其父类加载器,则会进一步向上委托,依次递归,直到最顶层启动类加载器
- 3.如果父类加载器可以完成类的加载任务,就可以成功返回,倘若服了加载器无法完成加载任务,子任务才会尝试自己去加载
- 双亲委派的优点:
- 避免类的重复加载
- 避免自己写的类动态替换java里面的核心类
- 能不能自己写个类叫java.lang.String?
- 通常不可以,但可以采取另类方法达到这个需求。
- 为了不让我们写String类,类加载采用委托机制,这样可以保证爸爸们优先,爸爸们能找到的类,儿子就没有机会加载。会先找到最顶层的String类将其加载,等到我们自己写的类时,拒绝加载
- 但是,我们可以自己定义一个类加载器来避免双亲委托机制,即而实行此类
6.沙箱安全机制
- 作用:防止恶意代码污染java源代码
- 比如上面我们定义了一个类名为 String 所在包也命名为 java.lang,因为这个类本来是属于 jdk的,如果没有