1.类加载器介绍
启动类加载器:是系统最底层的加载器,负责加载java的工具类,加载Jre/lib/rt.jar
扩展类加载器:这个一般不常用加载Jre/lib/ext/*jar这个目录下的所有数据
应用程序类加载器:主要加载Class_path指定目录所有jar,我们写的程序啊,第三方jar包spring,hebernate等都由此加载。
自定义加载器:有一些不在CLASS_PATH中,也不在Jre目录下,或者是网络流加载类,可以写自定义去加载。
前三个都是jvm自带的,后一个是我们自己开发。
下面依次讲讲这三个类都是干嘛的?
1.1启动类加载器
1.启动类加载器使用C语言开发
2.用于加载Java核心类库
JAVA_HOME/jre/lib/rt.jar、resources.jar ...运行时核心库。
{sun.boot.class.path}路径下的jar。
3.基于沙箱机制,只加载java、javax、sun包开头的类。
启动类加载器都是会加载固定的名称的类,也可以自定义sun.boot.calss.path路径的的jar,当然这种方式用的少,启动类加载器只加载java、javax、sun的包,因为出于安全考虑,如果电脑被黑客入侵以后往路径随便放个危险的文件被加载后会出现很大问题,出于这种考虑只拿这种做开头的类
1.2扩展类加载器
1.java语言编写,由sun.misc.Launcher$ExtClassLoader实现
2.上级加载器为启动类加载器
3.加载 JAVA_HOME/jre/ext扩展目录下的类库
如果你开发的jar放入该目录也会被扩展类加载器加载
1.3应用程序(系统)类加载器
1.java语言编写,由sun.misc.Launcher$AppClassLoader实现
2.应用程序加载器是默认的加载器,绝大多数类都由它加载
3.上级加载器为扩展类加载器
4.它负责加载CLASSPATH下的应用(三方)类库
示例:看看不同的类加载器
下面的SunEC我也不知道是什么类干什么的但是扩展类里有它就拿它做个测试
运行下:
我们自定义类ClassLoaderSample由应用程序类加载器加载
不同的类加载器操控自己不同的区域
2.自定义加载器
为什么会有自定义加载器?
在某些特殊场合下会用自定义加载器,自定义加载器的场景
1.字节码二进制流来自于网络
2.字节码文件不在指定的lib/ext/classpath路径下
3.需要对二进制流进行加工后才能得到字节码
字节码不是一个文件,需要网络传输调用就能用到自定义类加载,字节码文件不在扩展类的路径下需要自定义类加载,需要对流加工,比如加密,还原解密需要后才能得到字节码。
面试题:Class实例在JVM中是全局唯一么?
答:我们都知道加载类之前会有类是否被加载过的判断,所以是全局唯一的,但是这道题有前提,就是是在同一个加载器里是全局唯一的,不同的加载器产生的实例就是不同的就不是全局唯一了。
我们演示下示例更加了解自定义类加载器,也能知道jvm全局唯一不?
创建了两个自定义加载器:MyClassLoader1,MyClassLoder2
再创建一个ClassSample字节码,复制一个放到C盘,不属于启动类加载器,不属于扩展类加载器
打开MyClassLoader类,看看自定义加载器怎么实现?
1.首先:继承ClassLoader,重写findClass()
2.获取字节码二进制流
3.defineClass加载生成Class实例
打开MyClassLoader2,其实是和MyClassLoader1完全相同的,只不过是加载路径是D盘,演示一下上面的面试题,针对两个类不同名字的加载器,但是加载相同的字节码文件会有什么结果呢?
咱们打开测试类,通过new对两个类加载器进行实例化c1、c2,调用loadClass(“ClassSample”)后就会找到对应实例的findClass()
运行后发现两个类加载器完全不同,一个用MyClassLoader1,一个是MyClassLoader2,它们的hashCode也不同,代表不是一个实例,由此得出以下结论。
1.3 双亲委派模型
双亲委派就是:假如我自己自定义了一个类需要加载,此时通知系统类加载器,但是系统类加载器并不会加载因为它有上级,然后扩展类还有上级就是引导类加载器,相当于一直委派到引导类加载器,然后下一阶段就是依次加载了,引导类加载器加载的是java基本类库,所以加载不了我们自定义的类,再像下找就是扩展类加载器,扩展类是加载扩展类下的包,也加载不了自定义的,再向下找加载,找到了系统类加载器,是可以加载到我们自定义的类的。
那咱们现在加载一个java提供的Object类的话双亲委派是怎么工作的呢,首先还是系统类加载器开始,然后委派扩展类,再委派启动类加载器,然后启动类加载器加载发现是它加载的范畴进行加载,后续的扩展类和系统类加载器不再进行加载工作。
面试题:自定义类java.lang.Custom运行时会有什么问题?
会报错,不可以定义java.lang开头,这个是启动类加载器的范畴使用,但是却是自定义类,所以为了安全会报错。
示例: