[TOC]
## 动态加载
Java程序在运行时并不一定被完整加载,只有当发现该类还没有加载时,才去本地或远程查找类的.class文件并验证和加载;
当程序创建了第一个对类的静态成员的引用(如类的静态变量、静态方法、构造方法——构造方法也是静态的)时,才会加载该类。Java的这个特性叫做:动态加载。
### 一个类的初始化包括3个步骤
* 加载(Loading),由类加载器执行,查找字节码,并创建一个Class对象(只是创建);
* 链接(Linking),验证字节码,为静态域分配存储空间(只是分配,并不初始化该存储空间),解析该类创建所需要的对其它类的应用;
* 初始化(Initialization),首先执行静态初始化块static{},初始化静态变量,执行静态方法(如构造方法)。
根据java虚拟机规范,所有java虚拟机实现必须在每个类或接口被java程序首次主动使用时才初始化。
### 主动使用有以下6种:
* 创建类的实例
* 访问某个类或者接口的静态变量,或者对该静态变量赋值(如果访问静态编译时常量(即编译时可以确定值的常量)不会导致类的初始化)
* 调用类的静态方法
* 反射(Class.forName(xxx.xxx.xxx))
* 初始化一个类的子类(相当于对父类的主动使用),不过直接通过子类引用父类元素,不会引起子类的初始化(参见示例6)
* Java虚拟机被标明为启动类的类(包含main方法的)
### Bootstrap CLassloder
由C++编写的,它本身是虚拟机的一部分,所以它并不是一个JAVA类,也就是无法在java代码中获取它的引用
JVM启动时通过Bootstrap类加载器加载rt.jar等核心jar包中的class文件,之前的int.class,String.class都是由它加载
Bootstrap没有父加载器,但是它却可以作为任何一个ClassLoader的父加载器。比如ExtClassLoader
这句话的理解,必须结合后文中的 loadClass()过程,也就是在双亲委托模型中向上迭代父加载器查找时,如果父加载器为null,则jvm内置的加载器去替代,也就是Bootstrap ClassLoader
### Extention ClassLoader
加载目录%JRE\_HOME%\\lib\\ext目录下的jar包和class文件。
### AppClassLoader
加载当前应用的classpath的所有类
java虚拟机的入口应用,sun.misc.Launcher
## 双亲委托
### loadClass的实现
(向下一直找缓存,向上找实现)
1. 一个AppClassLoader查找资源时,先看看缓存是否有,缓存有从缓存中获取,否则委托给父加载器。
2. 递归,重复第1步的操作。
3. 如果ExtClassLoader也没有加载过,则由Bootstrap ClassLoader出面。
4. Bootstrap ClassLoader首先查找缓存,如果没有找到的话,就去找自己的规定的路径下,也就是sun.mic.boot.class下面的路径。找到就返回,没有找到,让子加载器自己去找
5. Bootstrap ClassLoader如果没有查找成功,则ExtClassLoader自己在java.ext.dirs路径中去查找,查找成功就返回,查找不成功,再向下让子加载器找
6. ExtClassLoader查找不成功,AppClassLoader就自己查找,在java.class.path路径下查找。找到就返回。如果没有找到就让子类找
7. 如果没有子类会抛出各种异常
### 为什么要使用这种双亲委托模式呢?
* 【重复】因为这样可以避免重复加载,当父亲已经加载了该类的时候,就没有必要子ClassLoader再加载一次。
* 【安全】考虑到安全因素,我们试想一下,如果不使用这种委托模式,那我们就可以随时使用自定义的String.class来动态替代java核心api中定义类型,这样会存在非常大的安全隐患,而双亲委托的方式,就可以避免这种情况,因为String.class已经在启动时被加载,所以用户自定义类是无法加载一个自定义的ClassLoade
自定义一个ClassLoader,默认加载路径为D:\\lib下的jar包和资源
### NoClassDefFoundError和ClassNotFoundExceptiom
NoClassDefFoundError:当java源文件已编译成.class文件,但是ClassLoader在运行期间在其搜寻路径load某个类时,没有找到.class文件则报这个错
ClassNotFoundException:试图通过一个String变量来创建一个Class类时不成功则抛出这个异常
- Java
- Object
- 内部类
- 异常
- 注解
- 反射
- 静态代理与动态代理
- 泛型
- 继承
- JVM
- ClassLoader
- String
- 数据结构
- Java集合类
- ArrayList
- LinkedList
- HashSet
- TreeSet
- HashMap
- TreeMap
- HashTable
- 并发集合类
- Collections
- CopyOnWriteArrayList
- ConcurrentHashMap
- Android集合类
- SparseArray
- ArrayMap
- 算法
- 排序
- 常用算法
- LeetCode
- 二叉树遍历
- 剑指
- 数据结构、算法和数据操作
- 高质量的代码
- 解决问题的思路
- 优化时间和空间效率
- 面试中的各项能力
- 算法心得
- 并发
- Thread
- 锁
- java内存模型
- CAS
- 原子类Atomic
- volatile
- synchronized
- Object.wait-notify
- Lock
- Lock之AQS
- Lock子类
- 锁小结
- 堵塞队列
- 生产者消费者模型
- 线程池