1、类加载的定义:
<1>、定义:将类的.class文件中的二进制数据读入到内存中。将其放在运行时方法区内,接着在堆中创建一个java.lang.Class对象,作为封装类在方法区的数据结构。
<2>、出现2个问题:
a、什么时候加载:
类加载器并不是等待某个类被首次使用时加载,JVM规范允许类加载器预先加载将被调用的类,如果遇到.class文件缺失或存在错误,类加载器必须在程序首次主动使用该类的时候才会报告错误(LinkageError),如果这个类一直没有被程序主动使用,那么类加载器就不会报告错误。
b、从哪里加载文件:
1、本地磁盘,2、网上加载 3、从数据库中,4、压缩文件 ,5、从其他文件生产的(JSP应用)
2、类加载的过程:
加载->链接(验证--> 准备 --> 解析) -->初始化--> 使用 -->卸载
注意:下面的流程是按顺序开始,不是按顺序执行。在各流程开始之后这些流程可能是交叉执行的。
PS:
1、静态成员变量赋予默认值就是在准备阶段。
2、如果在定义静态成员变量时赋值了,那么在初始化阶段才真正赋值
3、非静态 非final 成员变量 ,只有在产生实例时,一起分配在堆中
3.5、非静态 final 修饰的成员变量,只有在产生实例时,一起分配在堆中,但是需要在产生实例时,就要完成初始化。3种方式:
1、定义时直接赋值,2、静态与非静态初始化块中赋值 ,3、构造器中赋值
4、常量有2个地方赋值: 定义时赋值和静态初始化块时赋值
int --> 0 ,short --->0 ,long -->0,float --> 0.0f ,double -->0.0d ,boolean -->false, 引用类型为 null
3、类加载器
加载顺序: BootStrap ClassLoader > Extension ClassLoader > Application ClassLoader
启动类加载器 -- BootStrap ClassLoader :使用C++语言编写,加载jre/bin目录下的jar包到内存,或者是-Xbooclasspath参数指定的路径。
拓展类加载器 -- Extension ClassLoader :加载 jre/bin/ext目录下的jar包到内存,或者是java.ext.dirs 参数指定的路径。
应用类加载器 -- Application ClassLoader :加载编写的类-----当前项目的classpath 目录下的所有类到内存,如果没有自定义的加载器,则为默认的加载器。
自定义加载器:由自己决定加载哪些文件,分为2种:
<1> 、遵守双亲委派机制
继承ClassLoader 重写 findClass()方法
<2> 、违背双亲委派机制
继承ClassLoader 重写 loadClass()方法
双亲委派机制:
--> 目的:1、防止加载恶意代码,覆盖核心API等情况;2、避免重复加载
--> 具体过程:
1、类加载器收到加载的请求,
2、将这个加载请求委托给父类加载区加载,
3、继续步骤2 一直委托到 启动类加载器(BootStrap ClassLoader),
4、如果当前加载器没有加载到这个类,则通知下级类加载器加载,
5、继续 步骤4、一直到最下级的类加载器,途中如果加载到了,则结束,若所有加载器都没有加载到这个类,那么抛出异常---->ClassNotFindException
类加载的3种方式:
第1种:通过命令行启动应用时, 由JVM初始化加载含有main()方法的主类
第2种:通过Class.forName() 方法动态加载,会默认执行静态初始化块。其中,Class.forName(name,initialize,loader)中的initialze 可指定是否需要执行静态初始化块
第3种:通过ClassLoader.loadClass()方法动态加载,不会执行初始化块
如有问题或不足之处请指出!