Java系列(一)类加载机制

一.类加载的机制:
类加载(Class Loading)是一种机制,他描述的是将字节码以文件形式加载到内存再经过连接、初始化后,最终形成可以被虚拟机直接使用的Java类型地过程。
Class Loading 包含了加载(Loading)、连接(Linking)、初始化(Initialization)三大部分,其中Linking又包含了三个部分:校验(Verification)、准备(Preparation)、解析(Resolution)。而一个类的生命周期只是在Class Loader的基础上多了:使用(Using),卸载(Unloading)两部分。
类的生命周期如下:
Java系列(一)类加载机制

二、.类加载的流程:
Loading是Class Loading的第一步,他的工作是负责将字节码(bytecode)加载到JVM内存中,这个内存空间就是我们常说的方法区。在JVM规范中,Loading需要完成以下三点:
通过一个类的全限定名来获取定义此类的二进制字节流
将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构;
在内存中生成一个代表这个类的java.lang.Class对象,作为方法区这个类的各种数据的访问入口。
总而言之,类的加载过程,由类加载器完成,找到对应的字节码,创建一个Class对象
 类的加载的最终产品是位于堆区中的Class对象。Class对象封装了类在方法区内的数据结构,并且向Java程序员提供了访问方法区内的数据结构的接口。
Java系列(一)类加载机制
加载类的方式有以下几种:
  1)从本地系统直接加载
  2)通过网络下载.class文件
  3)从zip,jar等归档文件中加载.class文件
  4)从专有数据库中提取.class文件
  5)将Java源文件动态编译为.class文件(服务器)

三、类加载器:
为了完成加载过程中的第一条:”通过一个类的全限定名来获取定义此类的二进制字节流”的功能,JVM团队开发了一个模块——类加载器。
Java系列(一)类加载机制
(1)启动类加载器(Bootstrap ClassLoader):负责加载<\JAVA——HOME>\lib目录中的并且可以被虚拟机识别的;
(2)扩展类加载器(Extension ClassLoader):负责加载<\JAVA_HOME>\lib\ext目录中的所有类库,开发者可以直接使用扩展类加载器;
(3)应用程序类加载器(Application ClassLoader):它是ClassLoader中的getSystemClassLoader()方法的返回值,所以也称它为系统类加载器。它负责加载用户类路径(ClassPath)上所指定的类库,一般没有写自定义的类加载器的话,自己写的类都用Application加载器加载。
(4)自定义类加载器(User Classloader),通过继承ClassLoader实现,一般是加载我们的自定义类。

四、双亲委派模型(防止用户写了同名的系统内置的类)
双亲委派模型的工作过程是:
如果一个类加载器收到了类加载的请求,它首先不会自己去尝试加载这个类,而是把这个请求委派给父类加载器去完成,每一层次的类加载器都是如此,因此所有的加载请求,最终都应该传送到顶层的启动类加载器中,只有当父加载器反馈自己无法完成这个加载请求(它的搜索范围中没有找到所需的类)时,子加载器才会尝试自己去加载。
加入自己写了一个java.lang.String类加载该自定义的String类,该自定义String类使用的加载器是AppClassLoader,根据优先使用父类加载器原理,AppClassLoader加载器的父类为Extension ClassLoader,所以这时加载String使用的类加载器是Extension ClassLoader,但是类加载器ExtClassLoader在jre/lib/ext目录下没有找到String.class类。然后使用Extension ClassLoader父类的加载器BootStrap Classloader,父类加载器BootStrap Classloader在JRE/lib目录的rt.jar找到了String.class,将其加载到内存中。由于父类加载器已经加载了系统的java.lang.String类,所以这个自定义的String类就不会被加载,就无法使用。