序言:
1.什么是JVM?
- JVM就是将javac编译后的.class字节码文件翻译为操作系统能执行的机器指令
 - 翻译过程: 
  
- 前端编译:生成.class文件就是前端编译
 - 后端编译:通过jvm解释(或即时编译或AOT)执行
 
 - .class文件时跨平台的,jvm并不是跨平台的
 - 通过javap进行反编译
 
2.java文件是怎么变成.class文件的?
属于前端编译

3..class文件解读
- 采用16进制
 - magic、版本号、常量池(包括字面量、符号引用、接口、字段、方法等)、字段表集合、方法表集合
 - 符号引用就是类信息、修饰符、名称等
 
4.类加载机制(JVM的类加载子系统)
- 所谓的类加载机制就是将class文件加载进内存,并对数据进行校验,转换解析和初始化,使得JVM可以直接使用。
 - 如何加载进内存? 
  
- 常见的从本地系统加载
 - 动态代理
 - 从jar包加载
 
 - 类加载过程 
  
- 装载: 
    
- 通过类全限定名获取类的二进制字节流!这个过程可以做拦截增强
 - 将字节流代表的静态存储结构转换为方法区的运行时数据结构
 - 在堆中生成java.lang.class对象,作为对方法区中这些数据的访问入口(defineClass方法生成)
 
 - 链接 
    
- 验证:格式验证、字节码验证:跳转验证、符号引用验证、元数据验证:语法。-Xverify:none 取消验证。穿插在整个过程中
 - 准备:为静态变量赋值,初始化成默认值。 
      
- 这里不包含final修饰的static,final修饰的static都在编译的时候就分配了
 - 不会为实例变量分配初始化,类变量在方法区中,实例变量随着对象在堆中(即在实例构造器方法中进行的)
 
 - 解析 
      
- 将符号引用(名称、描述符、全限定名啥的)转换成直接引用,直接指向目标的指针(方法区里的指向)
 - 对解析结果进行缓存
 
 
 - 初始化 
    
- 对比于准备阶段,这里是通过指定主观计划去初始化变量和其他资源。有点懒加载的味道,需要使用的时候才加载
 - 对类变量设置初始值的两种方式: 
      
- 直接声明
 - static代码块
 
 - 步骤 
      
- 先装载和链接本类
 - 然后初始化父类
 - 初始化自己
 
 - 什么时候加载(初始化):(主动引用) 
      
- 创建实例;final在调用构造方法前就要弄好
 - 使用静态变量或者静态方法的时候
 - 调用子类父类也会初始化;
 - 标明启动类的类,或者像object和class类启动时候就加载了
 - 反射的时候
 
 - (被动引用) 
      
- 定义类数组不会初始化
 - 使用父类的静态变量,不会初始化
 - 使用static final不会初始化
 
 
 - 卸载: 
    
- 用完之后就卸载回收
 - 所有实例被回收,classloader被gc回收,class对象没有被任何地方引用
 
 
 - 装载: 
    
 
5.类加载器
-  类加载器: 
  
- 就是读取字节码,转换成java.lang.class类的一个实例的代码模块
 - 一个类在同一个类加载器中具有唯一性,不同类加载器是允许同名类存在的,类加载器不同,就不会是同一个类。
 - 分类: 
    
- Bootstrap classloader:负责java_home的所有class,核心类库
 - Platform classloader:负责一些扩展的包
 - Application classloader:classpath中指定的包
 - custom classloader:根据程序自定义类加载器
 
 - 为什么要分层? 
    
- 如果自己编写了一个String类,如果只有一个的话无法判定究竟要加载哪个。所以分层对信任级别进行划分
 - 即使打破了双亲委派也不能重写String,defineClass限制了限定类名不能以java开头,除非自己将二进制流转换成class对象
 
 - 三个特性: 
    
- 全盘负责: 
      
- 当一个类加载器加载某个class的时候,该class所依赖的和引用其他的class都由该类加载器负责载入。除非显式使用另一个类加载器
 
 - 父类委托(双亲委派): 
      
- 首先传入类的全限定名
 - 为什么:实现带有优先级的层次关系
 - 从app层依次往上找是否加载过,然后又从上往下看谁能加载,最后还没有就抛异常。
 - 可以重写loadclass打破双亲委派
 - 打破: 
        
- SPI,JDK提供了一套接口,定义实现类,在META-INF/services中注册实现类的相关信息,比如JDBC的DriverManager
 - OSGI:热部署、热替换
 - 如果怕打破可以重写findclass方法
 
 
 - 缓存机制: 
      
- 加载过的class文件在内存中(方法区)缓存
 - 每一个类加载器都有自己的缓存
 
 - 打破父类委托: 
import java.io.IOException; import java.io.InputStream; public class CustomClassLoader extends ClassLoader { public CustomClassLoader(ClassLoader parent) { super(par 
 - 全盘负责: 
      
 
 










