jvm中java类加载机制,双亲委派

java指令到底干了些什么?我们些的java代码是如何被加载到jvm内存中执行的?

实现自定义的类加载器。实现自己的热加载。实现同类多个版本共存。

类加载具有五个阶段:加载、验证、准备、解析、初始化

加载:将java中的class字节文件加载进入堆内存中。

验证:验证该类是否正确,class文件不能对虚拟机造成危害,验证文件格式,元数据,字节码,符号引用验证。

准备:java类中又许多其他变量,变量分为两种,一种是类变量,一种是实例变量,类变量就是具有static定义的变量。这时候需要根据定义类型去开辟空间准备。

           int 默认是0,long默认是0L等等。无论类中打算赋值多少。都先准备初始值。

解析:主要是将虚拟机常量池中的符号引用转为直接引用。

初始化:将在准备阶段准备好的变量。在这里根据java类的定义,赋值。

java的类加载机制:

java的类加载体系:BootStrao classloder > ExtclassLoader->Appclassloader

BootStrao classloder(启动类加载器):底层采用c++实现,主要是加载jdk\jre\lib自带的类库,不能直接引用。

ExtclassLoader(扩展类加载器):负责加载jdk\jre\lib\ext中,或者系统知道路径的类库。开发中可以使用该加载器

Appclassloader(应用程序加载器):负责加载ClassPath应用程序的所有指定的类。可以直接使用。

每种类加载器都有他自己的加载目录。

双清委派:一个类java加载进jvm的过程

每个类加载器对他加载过的类都有一个缓存。

向上委托查找,向下委托加载。

描述:一个类如果需要加载,首先会让Appclassloader进行加载,Appclassloader会先去自己的缓存中查找,如果没有。

委托给自己的上一级ExtclassLoader加载,ExtclassLoader又回去自己的缓存中查找,如果没有继续委托给上级BootStrao classloder。

这时候如果BootStrao classloder还是没有,会去自己的加载目录里面进行查询加载,如果目录里面没有委托给自己下级ExtclassLoader。

ExtclassLoader就也会去自己的加载目录加载,如果还是没有再委托给下级Appclassloader进行加载。Appclassloader也去自己的加载目录里找。

如果没有找到,出现异常,没有该类。  这个流程中只有有一步找到就停下来。

目的是:对JDK中的类进行保护,防止覆盖。

JDK中还有沙箱保护机制进行保护。就是包名不能是JDK一样的包目录。

JDK的类加载对象:

ClassLoader->SecureClassLoader->URLclassLoader->ExtclassLoader,AppClassLoader

代码拆分:

可以通过URLclassLoader调用远程JAR包,这时候可以使用反射的方式,指定反射类调用对应的方法,或者创建对象。

jar包混淆:

需要自定义类加载器。可以实现SecureClassLoader接口

重写findClass方法,读取字节码,拿到字节码以后。调用defineClass方法.就可以实现

就可以加载其他文件的编码代码了,不一定需要是class文件。

可以通过对二进制文件,字节码进行简单的混淆,做少量的修改,这样class安全性得到提升。

热加载:

java里的每一个类加载器,对他加载过的类,都会保留一个缓存没。正是这个缓存,导致我们无法实现热加载。

可以通过每次new一个SalarylartLoader的方式,实现热加载。

缺点:因为热加载机制有一个加载的过程,很容易出错,还有一个更大的问题是,热加载必然产生非常多的垃圾对象。

在ClassLoader的loadClass方法中,还加入了一个布尔参数

热加载机制,可以在编译中能发现的问题,全都到了运行时中,会对程序照成很大影响。

打破双亲委派机制

有可能写了类加载过程中,本地代码中又不小心写了一个同样的类,这时候双亲委派机制,会优先加载本地代码。而不是jar包中的代码。

通过打破双亲委派机制,我们可以实现需要加载的类优先从jar包中加载,而不是本地代码类。

打破双亲委派后,出现问题,会加载出两个类,而且这两个类的类型无法转换。

总结:

java类加载机制,是jdk源码像JVM底层学习的一个门户。

实现的类加载流程,模拟的tomcat的类加载机制。

spi机制,jdbc.

猜你喜欢

转载自blog.csdn.net/miwanmeng/article/details/115226675