我们都知道java中类有很多,所有的类并不是一开始就放入了虚拟机中,只有当需要用到它的时候,系统才会去调用它,所以才用到了类加载器,这是一个动态的过程,除了动态加载类以外,还会动态初始化类,对类进行动态链接。
一、类加载器
java中有三种类加载器。每个类加载器在创建的时候已经指定他们对应的目录, 也就是说每个类加载器去哪里加载类是确定的,下面是三种类加载器和他们对应的路径:
1.BootStrapClassLoader(根类加载器),用来加载JRE/lib/rt.jar中的类,java的核心类,用原生代码实现的,由C++实现。下面给大家展示一下用代码查看根类加载器所加载的核心类库。
2.ExtClassLoader(扩展类加载器), 用来加载jre/lib/ext目录下或者java.ext.dirs系统属性定义的目录下的类,由java语言写的,父类加载器为null。
3.SystemClassLoader(系统类加载器), 用来加载classpath指定的路径中的类,由java语言实现,父类加载器为ExtClassLoader。
二、类加载机制
JVM的类加载机制主要有如下3种:
1.全盘负责:当一个类加载器负责加载某个class时,该class所依赖和引用其他class也将由该类加载器负责注入,除非显示使用另一个类加载器注入。
2.双亲委派:当系统要调用某个类时,会首先调用它的父类加载器去加载,如果它的父类加载器无法加载,就会通知它本身加载,通俗点讲就是某个特定的类加载器在接到加载类的请求时,首先将加载任务委托给父类加载器,依次递归。如果父类加载器可以加载成功,就返回,如果父类无法加载,才自己去加载。来看下双亲委派模型:
3.缓存机制:缓存机制保证所有加载过的class将会被缓存,当程序中需要某个类时,类加载器会先从缓存区中寻找该类,如果没有,系统才会读取该类对应的二进制数据,并将其转换成class对象,存入缓冲区中。
这里着重说下双亲委派模型,采用双亲委派的模式的好处是Java类随着它的类加载器一起具备了一种带有优先级层次的关系,通过这种层级关系可以有效避免一个类被重复加载。还有一方面是安全因素,假设通过网络传递一个名为java.lang.String的类,通过双亲委派模式传递到根类加载器,这个加载器在java核心API发现这个名字的类,就不会重新传送,防止API库被随意纂改。