JVM之ClassLoader工作机制

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/zanpengfei/article/details/86302412

ClassLoader功能:将Class加载到JVM中、审查每个类应该由谁加载,采用父优先的登记加载机制、将Class字节码重新解析成JVM统一要求的对象格式。

1、整个JVM平台提供3层ClassLoader,这3层ClassLoader可以分为俩种类型,可以理解为为接待室服务的接待室和为会员服务的接待室。

1)BootstrapClassLoader:就是接待室服务自身的,主要加载JVM自身工作需要的类,完全是由JVM自己控制,这个ClassLoader不遵循类加载规则,仅仅是一个类类的加载工具而已,没有更高一级的父加载器,也没有子加载器

2)ExtClassLoader:该加载器是JVM自身一部分,但他不是JVM亲自实现的,他加载那些既不是JVM内部的,也和普通的外部会员不同的类,服务的特定目标在System.getProperty(“java.ext.dirs”)目录下

3)AppClassLoader:该类加载器专门用于接待会员服务的,父类ExtClassLoader,在System.getProperty(“java.class.path”)目录下的类都能被这个类加载

4)从源码中可以看出2、 3加载器都属于Launcher类中的静态内部类,而且他们都继承URLClassLoader类,System.getProperty(“java.ext.dirs”)目录下是由ExtClassLoader加载,其他都是由AppClassLoader来加载。

5)JVM加载class文件到内存中的俩种方式:

隐式加载:就是不通过代码里调用ClassLoader来加载需要的类,而是JVM需要应用某个类的时候,发现该类不在内存中,则自动加载到内存中。
显示加载:与隐式加载相反,是我们在代码中调用ClassLoader类来加载。

2、加载class文件步骤

1)第一个阶段找到.class文件并且将其包含的字节码加载到内存中。

2)第二阶段分为三个步骤:分别是字节码验证、Class类数据结构分析、内存分配、符号表的链接。

3)第三个阶端对类中静态属性和初始化赋值以及执行静态块。

 3、加载类常见的错误

1)ClassNotFoundException:原因是当JVM要加载指定的文件的字节码都内存中时,找不到该文件,解决的方式是检查当前的classpath目录下是否有指定的文件,如果不值到当前的classpath路径,可以通过this.getClass().getClassLoader().getResource(“”).toString();

2)NotClassFoundException:JVM找不到给文件,解决方式是确保每个类引用类都在当前的classpath下面。

3)UnsatisfiedLinkError:通常是在啊JVM启动时,如果不小心将在JVM中的耨个lib删除了,可能会报这么错。

4)ClassCastExcep.tion:程序中在出现强制类型转换时,可能会出现,解决方式:显示指明容器所包含的对象类型或者先通过instanceof检查。

5)ExceptionInInitializerError:如果初始化器爆出一些Exception,但该异常不是error也不是他的某个子类。

4、加载机制:

1)WebAppClassLoader加载机制:

a)首先检查在WebAppClassLoader中是否已被加载过,如果请求的类以前在WebappClassLoader加载的,那么肯定在WebappClassLoader的缓存容器resourceEntries中,如果不在,则继续检查在JVM虚拟机是否已经加载过,也就是调用ClassLoader的findLoadedClass方法;

b)如果前俩个缓存中都没有,则先调用SystemClassLoader加载请求的类,SystemClassLoader在这里是AppClassLoader;

c)检查请求的类是否在packageTriggers定义的包名下,如果在则通过StandardClassLoader类加载;如果仍然没有找到,则由WebappClassLoader加载,其将在应用的WEB-INF/classes目录下查请求的类文件的字节码,找到后创建一个ResourceEntry对象保持类的元信息,并将其保持在WebappClassLoader的resourceEntries容器,便于下次查找,接着将调用defineClass方法生成请求Class对象并返回给InstanceManager来创建实例。

2)Servlet容器启动过程:ContextConfig的初始化init方法主要完成的工作:

a)创建用于解析XML配置文件的contextDigester对象

b)读取默认的context.xml配置文件,如果存在则解析它

c)读取默认的Host配置文件,如果存在则解析它

d)读取默认的Context自身的配置文件,若存在则解析

e)设置Context的DocBase

3)ContextConfig的init方法完成后,Context容器会执行startInternal方法,该方法启动逻辑主要包括以下部分:

a)创建读取资源文件的对象

b)创建ClassLoader对象

c)设置应用的工作目录

d)启动相关的辅助类,如logger、realm、resource等

e)修改启动状态,通知感兴趣的观察者(Web应用的配置)

f)子容器的初始化。

g)获取ServletContext并设置必要的参数

h)初始化“load on startup”的Servlet。

猜你喜欢

转载自blog.csdn.net/zanpengfei/article/details/86302412