志在指尖
用双手敲打未来

ClassLoader&双亲委派&类初始化过程

1.classsycle
类加载的生命周期:加载(Loading)–>验证(Verification)–>预备(Preparation)–>解析(Resolution)–>初始化(Initialization)–>运用(Using)–>卸载(Unloading)。
关注点1:loading将class二进制文件加载到内存中
经过一个类的全限定名来获取界说此类的二进制字节省。
将这个字节省所代表的静态存储结构转化为办法区的运转时数据结构。
在java堆中生成一个代表这个类的java.lang.Class目标,做为办法区这些数据的访问进口。
加载阶段完结之后二进制字节省就依照虚拟机所需的格局存储在方区去中。
关注点2:verifaction这一阶段的意图是为了确保Class文件的字节省中包括的信息契合当时虚拟机的要求
文件格局验证:验证字节省是否契合Class文件格局的标准,而且能被当时版别的虚拟机处理
元数据验证:对字节码描绘的信息进行语义分析,以确保其描绘的信息契合java言语标准的要求。
字节码验证:这个阶段的首要作业是进行数据流和控制流的分析。使命是确保被验证类的办法在运转时不会做出危害虚拟机安全的行为。
符号引证验证:这一阶段发生在虚拟机将符号引证转换为直接引证的时分(解析阶段),首要是对类本身以外的信息进行匹配性的校验。意图是确保解析动作能够正常履行。
关注点3:preparation对静态变量赋默许值,而不是初始值(方针指),预备阶段是正式为静态变量分配内存并设置初始值,这些内存都将在办法区中进行分配,这儿的变量仅包括类变量(静态变量)不包括实例(成员)变量。java手写多级缓存
关注点4:resolution:解析是虚拟机将常量池的符号引证替换为直接引证的进程
符号引证:符号引证以一组符号来描绘所引证的方针,符号可所以任意形式的字面量,只要运用时能无歧义地定位到方针即可。符号引证与虚拟机完结的内存布局无关,引证的方针并不一定现已加载到内存中。
直接引证:直接引证可所以直接指向方针的指针,相对偏移量或是一个能直接定位到方针的句柄。直接饮用是与内存布局相关的。
类或接口的解析
字段的解析
类办法解析
接口办法解析
关注点5:initializing担任履行类中的静态初始化代码、结构器代码以及静态属性的初始化(方针值)initializing担任履行类中的静态初始化代码、结构器代码以及静态属性的初始化(方针值)
遇到new、getstatic、putstatic、invokestatic这4个字节码指令时,假如类没有进行过初始化,动身初始化操作。访问final变量除外??
运用java.lang.reflect包的办法对类进行反射调用时。
当初始化一个类的时分,假如发现其父类还没有履行初始化则进行初始化。
虚拟机启动时用户需求指定一个需求履行的主类,虚拟机首要初始化这个主类。
动态言语支撑java,lang.invoke.MethodHandle解析成果为REF_getstaticREF_invokestatic的办法句柄时,该类有必要初始化。
留意:接口与类的初始化规则在第三点不同,接口不要气一切的父接口都进行初始化。
2不同类加载器说明
引导类加载器(BootStrap):
首要担任加载JVM本身需求的类,该加载器由C++完结,加载的是/lib下的class文件,或许-Xbootclasspath参数指定的途径下的jar包,留意有必要由虚拟机依照文件名识别加载jar包,如rt.jar,假如文件名不被虚拟机识别,即便把jar丢到lib目录下也是没有最用的(出于考虑,Bootstrap启动类加载器只加载java、javax、sun最初的类),引导类加载器在hotspot虚拟中运用C++言语完结,它是虚拟机的一部分。除了引导类加载器之外,其他类加载器都是由Java言语完结,而且全部集成自java.lang.ClassLoader,他们是独立于虚拟机外部的。
扩展类加载器(Extension):
扩展类加载是指Sun公司完结的类,它是由Sun的ExtClassLoader完结的,是Lancher类的静态内部类。他担任加载/lib/ext目录下或有体系变量-Djava.ext.dir指定途径中的类库,开发者能够直接运用标准扩展类加载器
ViewCode
体系类加载器(运用程序加载器AppClassLoader):
它是由Sun的AppClassLoader完结的,它担任加载体系途径java-classpath或许-Djava.class.path指定途径下的类库,也便是我们经常运用到的classpath途径,开发者直接运用体系类的加载器,一般情况下该类加载器是程序组中默许的类加载器,经过ClassLoad.getSystemClassLoader()办法能够获取到该类的加载器。
自界说类加载器(CustomClassLoader):
在程序运转期间,经过java.lang.ClassLoader的子类动态加载class文件,体现java动态实时类装入特性
3.ClassLoader加载类进程(双亲派遣)
JVM在加载类时默许采用的双亲派遣机制。通俗讲,便是某个特定的类加载器在接到类加载器的恳求时,受限将加载使命委传给父类加载器,依次递归,假如父类加载器能够完结类的加载使命,就返回成功;只有父类加载器无法完结此加载器使命时,才去自己加载
4.ClassLoader加载类进程(双亲派遣流程图)
5.为什么需求双亲派遣机制?
为了体系类的安全,类似“java.lang.Object”这种中心类,JVM需求确保他们生成的目标都会被认定为同一类型,假如用户编写了一个lava.lang.Object的同名类并放在ClassPath中,多个类加载器都去加载这个类到内存中,体系中会出现多个不同的Object类,那么类之间的比较傲成果以及唯一性将无法确保,而且假如不运用这种双亲派遣模型将会给虚拟机的安全带来安全隐患。所以要让类目标进行比较有意义,条件是他们要被同一个类加载器加载。即“经过代理形式,对于java中心类库的类的加载作业由引导类加载器一致完结,确保了Java运用所运用的都是同一个版别的Java中心库的类,是相互兼容的”
好处是防止内存中出现多份相同的字节码。
6.能不能自己写个类叫java.lang.System?答案:通常不能够,但能够采纳另类办法到达这个需求。
解说:为了不让我们写System类,类加载采用托付机制,这样能够确保爸爸们优先,爸爸们能找到的类,儿子就没有机会加载。而System类是Bootstrap加载器加载的,就算自己重写,也总是运用Java体系供给的System,自己写的System类底子没有机会得到加载。
但是,我们能够自己界说一个类加载器来到达这个意图,为了防止双亲托付机制,这个类加载器也有必要是特别的。因为体系自带的三个类加载器都加载特定目录下的类,假如我们自己的类加载器加载一个特别的目录,那么体系的加载器就无法加载,也便是最终还是由我们自己的加载器加载。
7.如何自界说类加载器
承继ClassLoader
overwritefindClass()
8.如何打破双亲派遣?
集成ClassLoader
重写loadClass办法

未经允许不得转载:IT技术网站 » ClassLoader&双亲委派&类初始化过程
分享到: 更多 (0)

评论 抢沙发

评论前必须登录!

 

志在指尖 用双手敲打未来

登录/注册IT技术大全

热门IT技术

C#基础入门   SQL server数据库   系统SEO学习教程   WordPress小技巧   WordPress插件   脚本与源码下载