类加载小笔记

        在JVM中并不是一次性把所有的文件都加载到,而是一步一步的按照需要来加载。比如JVM启动时,会通过不同的类加载器加载不同的类。当用户在自己的代码中,需要某些额外的类时,再通过加载机制加载到JVM中,并且存放一段时间,便于频繁使用。说的通俗点就是,被调到的接口(首次调用)相关的类都会被加载到JVM中,没有调用的不会被JVM加载,按需加载~

      那什么叫类的加载呢

类的加载又称为类的初始化,实际上可细分为类的加载、连接、初始化。下面将讲述着三个阶段的过程。

类的加载:指.class文件读入内存,并为之创建一个 java.lang.Class对象。类加载,是通过类加载器来完成的,类加载器通常由JVM提供,通常称为系统类加载器(也可以是自己写的加载器,只要继承ClassLoader基类)。类加载无须等到“首次使用该类”时加载,jvm允许预加载某些类。   

连接: 负责把类的二进制数据合并到JRE(java运行环境)中
1.验证 检测被加载的类是否有正确的内部结构,并和其他类协调一致
2.准备 负责为类的类变量(非对象变量)分配内存,并设置默认初始值
3.解析 将类的二进制数据中的符号引用替换成直接引用

初始化: 主要对类变量(而非对象变量)的初始化
声明类变量的初始值 = 静态初始化块 他们是相同的,等效的。都会被当成类的初始化语句,JVM会按照这些语句在程序中的顺序依次执行他们

1.假设类还没有被加载和连接,那么先加载和连接该类
2.假设该类的父类还没被初始化,那么先初始化父类 ----jvm总是最先初始化java.lang.Object类
3.假设类中有初始化语句,则一次执行这些初始化语句

当程序主动使用任何一个类时,系统会保证该类以及所有父类(直接父类和间接父类)都会被初始化

     那类有哪些加载时机呢?

  1. 创建类的实例。new,反射,反序列化
  2. 使用某类的类方法--静态方法
  3. 访问某类的类变量,或赋值类变量
  4. 反射创建某类或接口的Class对象。Class.forName("Hello");---注意:loadClass调用ClassLoader.loadClass(name,false)方法,没有link,自然没有initialize
  5. 初始化某类的子类
  6. 直接使用java.exe来运行某个主类。即cmd java 程序会先初始化该类。  

      那么类的加载机制呢?

  1. 全盘负责。某类以及其所依赖的所有类,都由一个加载器负责加载。除非显示使用另外一个加载器。
  2. 父类委托。先父类加载器加载改Class,不行后,才尝试从自己的类路径中加载该类
  3. 缓存机制。缓存机制将会保证所有加载过的Class都会被缓存。。当程序需要Class时,先从缓存区中寻找Class对象,没有的话,才加载该类的.class对象。

      那么类的加载过程呢?        

  1. 检测此Class 是否被载入过(即在缓存区中是否由此 Class),有,则进入第8步,否则执行第2步。
  2. 如果父类加载器不存在(要么parent 一定是根类加载器,要么本身就是根类加载器),则跳到第4步;如果父类加载器存在,则执行第3步。
  3. 请求使用父类加载器去载入目标类,如果成功则跳到第8步,否则执行第5步
  4. 请求使用 根类加载器 载入目标类,成功则跳到第8步,否则跳到第7步
  5. 当前类加载器 尝试寻找 Class文件(从与此ClassLoader相关的类路径中寻找),如果找到则执行第6步,否则跳到第7步。
  6. 从文件中载入Class,成功后跳到第8步。
  7. 抛出ClassNotFoundException异常。
  8. 返回对应的 java.lang.Class对象。
    其中 第5,6步允许重写ClassLoader的findClass()方法来实现自己的载入策略,甚至重写loadClass()方法来实现自己 的载入过程
发布了100 篇原创文章 · 获赞 300 · 访问量 68万+

猜你喜欢

转载自blog.csdn.net/win7system/article/details/83579659