JVM运行和类加载过程
类加载机制:
JVM把 class 文件加载到内存,并对数据进行校验、解析和初始化,最终形成JVM可以直接使用的 Java 类型的过程
- 加载
将 class 文件字节码内容加载到内存随,并将这些静态数据转换成方法区中的运行时数据结构,在堆中生产一个代表这个类的java.lang.Class对象,作为方法区类数据的访问入口 - 链接
- 验证:确保加载的类信息符合JVM规范,没有安全方面的问题
- 准备:正式为类变量(static)分配内存并设置类变量初始值的阶段,并在方法区中分配
- 解析:虚拟机常量池内的符合引用替换直接直接应用的过程
- 初始化
初始化阶段时执行类构造器()方法的过程。类构造器()方法是由编译器自动收集类中的所有类变量的赋值动作和静态语句块(static块)中的语句合并产生的
当初始化一个类时,如果发现其父类还没有初始化过,则需要先触发其父类的初始化
虚拟机会保证一个类的()方法在多线程环境中被正确加锁和同步
类的引用:
- 主动:
- new一个类对象
- 调用类的静态成员(final 常量除外)和静态方法
- 使用java.lang.reflect包的方法对类进行反射调用
- 当虚拟机启动,则一定会初始化类
- 初始化时,若父类没有被初始化,则先初始化其父类
- 被动:
- 当访问一个静态域时,只有真正声明这个域的类才会被初始化,通过子类引用父类的静态变量,不会导致子类初始化
- 通过数组定义类引用,不会触发类的初始化
- 引用常量不会触发类初始化
类加载器
类加载器原理
将class文件字节码内容加载到内存中,并将这些静态数据转换成方法区中的运行时数据结构,在堆中生产一个代表这个类的 java.lang.Class 对象,作为方法区类数据的访问入口
类缓存:
标准的 Java SE类加载器可以按要求查找类,若某个类加载到类加载器中,将维持加载一定时间(缓存),后期被 JVM 垃圾回收器回收
ClassLoader类:
根据指定的类名称,找到或生成对应的字节代码,然后从这些字节代码中定义出一个 Java 类,即 java.lang.Class 类的一个实例
ClassLoader 还负责加载 Java 应用所需的资源,如图像文件和配置文件等。
类加载器树状结构、双亲委托代理机制
启动类加载器:
加载 Java 的核心库(JAVA_HOME/jre/lib/rt.jar)
加载扩展类和应用程序类加载器,并指定他们的父类加载器
扩展类加载器:
加载 Java 扩展库(jre/ext/*.jar),Java 虚拟机的实现会提供一个扩展库目录,该类加载器在此目录中查找并加载 Java 类
应用程序类加载器:
根据 Java 应用的类路径classpath来加载类,一般使用的类都是其加载的
自定义类加载器:
通过继承ClassLoader类实现自定义类加载器
双亲委托机制:
当类加载器在接收到加载类请求时,先将加载任务委托给父类加载器,依次追溯,直到最高的类加载器,如果父类完成加载任务,则返回成功,否则子类去完成加载任务
双亲委托机制时为了保证 Java 核心库的类型安全,杜绝了用户自定义Object类的情况
类加载器除了用于加载类,也是安全的最基本屏障
- 双亲委托机制是代理模式的一种,并不是所有的类加载器都采用此模式,Tomcat服务器使用的代理模式则不同,其先加载某个类,若不成功再委托给父类加载器
半脸懵逼