JVM类加载和双亲委派模型
类加载子系统
作用:将字节码文件加载到居jvm中,在类第一次被使用时,是需要初始化类文件
过程:装载、链接、初始化
装载:功能就是来加载类,使用到了三个类加载器,分别是Bootstrap ClassLoader、Extension ClassLoader和Application ClassLoader
链接:
1、验证:字节码验证器将验证生成字节码是否正确,如果验证失败,将得到验证错误
2、准备:对于所有的静态变量,进行分配内存并给定默认值 tmp分配内存,并给定默认值null
3、解析: 将所有的符号内存引用替换为方法区的原始引用
初始化:静态变量将被赋予原始值,静态代码块将被执行
类加载器
负责将字节码加载到内存中
类加载器的介绍
Bootstrap ClassLoader:启动类加载器
作用:负责加载JAVA_HOME的jre/lib/rt.jar里面所有的class
Extension ClassLoader:扩展类加载器
作用:负责加载java平台中扩展功能的一些jar包,包括JAVA_HOME中除jre/lib/*.jar或者-DJava.ext.dirs=XXX指定路径下的jar包
Application ClassLoader:应用类加载器
作用:负责加载classpath中指定的jar和目录中的class
双亲委派模型
通过双亲委派模型来加载类的过程如下:
1、当前类加载器会从自己已经在家的类中查询是否此类已经加载,如果已经加载则返回原来已经加载的类
2、如果没有找到,就会委托父类记载其去加载,父类加载器采用同样的策略,查看自己已经加载的类中是否包含这个类,有责返回,没有的话就委托给父类去加载,直到委托给启动类加载器为止,因为启动类加载器父类为空,到启动类加载器就不会在往上进行委托
3、如果启动类加载器加载失败,就会使用扩展类尝试加载,继续失败的话则会使用应用类加载器来加载,继续失败就会抛出一个异常:ClassNotfoundException
首先查找自身已加载的类->委托父类->尝试在记载器指定路径下加载
双亲委派的好处
1、安全性,避免用户自己编写的类动态替换java的一些核心类
如果不采用双亲委派模型的加载方式进行类的加载工作,那我们就可以随时使用自定义的类来动态替代Java核心API中定义的类。
例如:如果黑客将“病毒代码”植入到自定义的String类当中,随后类加载器将自定义的String类加载到JVM上,那么此时就会对JVM产生意想不到“病毒攻击”。而双亲委派的这种加载方式就可以避免这种情况,因为String类已经在启动时就被引导类加载器进行了加载。
2、避免类的重复加载
因为JVM判定两个类是否是同一个类,不仅仅根据类名是否相同进行判定,还需要判断加载该类的类加载器是否是同一个类加载器,相同的class文件被不同的类加载器加载得到的结果就是两个不同的类。