一、概念解释
1、JVM类加载:将.java
文件编译成.class
文件,加载类将.class
文件加载到jvm内存的过程。
加载过程分为:加载、验证、准备、解析、初始化;
加载:就是jvm类加载;
验证:验证二进制的.class
文件的是否符合jvm的规范;
准备:静态变量赋初始化值并分配内存; 如: static int a =0; static String name =null(
这步赋值根据类型默认值);
解析:将符号引用替换为直接引用,该阶段会把静态
方法在内存中通过指针的方式分配内存(直接引用
),所谓的静态连接,在类加载过程中执行;还有一些被
调用的
方法,会在运行时何时用到何时进行加载分配内存地址,这些是所谓的动态连接;
初始化:对类的静态变量进行实际赋值,并且执行静态
代码块; 如:static int a =666; static String name ="hello word";
类被加载到
方法区中后主要包含:运行时常量区,类型信息,
方法信息,字段信息,类加载的引用,对应class的实例;

2、类加载机制
双亲委派机制:由父加载器加载类,如果加载不到由子加载器加载(父加载和子加载不是父子关系,是上下级关系);如下图:
引导类加载器(BootStrapClassLaoder): 加载jdk核心类库,jdk/jre/lib/rt.jar 等等;
扩展类加载器 (ExtClassLaoder): 加载jdk/jre/lib/ext/.jar 等等;
应用类加载器 (AppClassLoader): 加载程序员自己写的类, Cla
sspath路径下的类;

3、为什么要用双亲委派机制?
沙箱安全机制:JDK是java最核心的类库,也是java开发必需环境,如果随便就可以更改,随便
一个黑客就可以写同
一个类比如:String类等等, 那么JDK早已沦陷;
避免重复加载相同包
名称下的相同类;
二、源码双亲委派机制
3、为什么要用双亲委派机制?
沙箱安全机制:JDK是java最核心的类库,也是java开发必需环境,如果随便就可以更改,随便
一个黑客就可以写同
一个类比如:String类等等, 那么JDK早已沦陷;
避免重复加载相同包
名称下的相同类;
二、源码双亲委派机制
1、由c++实现引用启动类,然后
调用Launcher类中的getLauncher()
方法创建单例Launcher对象 ;

2、new Launcher()对象
调用Launcher构造
方法,创建ExtClassLaoder与AppClassLoader类加载器,并且把ClassLoader赋值为AppClassLoader类加载器;

3、this.loader = Launcher.AppClassLoader.getAppClassLoader(var1);跳进getAppClassLoader(var1)进入AppClassLoader类
调用loadClass()
方法最终
调用父类的loadClass()
父类为:Classloader类中loadClass()
方法执行双亲外派机制;



(
注上图:当前是AppClassLoader加载器,Class<?> c = findLoadedClass(name);首先判断要加载类是否已载,如果是直接返回,如果否,就获取当前加载器的parent是ExtClassLoader加载器去加载,如果没有,再次获取ExtClassLoader加载器的parent,因为引用类加载器BootStrapClassLoader加载器是c++编写的,java语言是无法获取的,参数值为null,所以parent为null,)所以执行c = findBootstrapClassOrNull(name);方法)

(注上图:当c 变量为空,这是就是执行if代码块中的代码,最终如果父加载器都没有加载成功,就会调用当前加载器AppClassLoader加载器的findClass(name )方法)

(注上图:因为AppClassLoader加载器没有重写findClass()方法,所以调用父类urlclassloader类的findClass()方法,获取classpath路径的类,进行加载,最后调用defineClass()方法进行执行验证、准备、解析、初始化)
三、实现
自定义加载器
1、实现
自定义加载器其实很简单,我们分析加载器最重要的就是通过双亲委派机制来实现,那么这个机制的源码实现ClassLoader类中loadClass
方法,所以我们只要
自定义类然后继承ClassLoader类就可以了;
2、当然
自定义加载器肯定要加载咱们
自定义路径下的类,通过双亲委派机制的源码我们很清楚的知道,
urlclassloader类下的findClass()
方法加载了Cla
sspath路径的类,所以我们只要重写这个
方法,让我们加载器去
获取我们
自定义的路径类就可以了(注:
自定义加载器的父加载器是应用加载器(appClassLoader))

四、打破双亲委派机制
1、其实打破双亲委派机制也不难,我们通过源码分析知道双亲委派机制是在ClassLoader类中loadClass()
方法实现的,所以只要重写loadClass()
方法,把有关双亲外派机制的逻辑
代码去掉就可以了;(特别注意:本人遇到坑,程序员自己写的类,很多时候还是会用到JDK类库的核心类,比方你创建了User类,但是它的
父类是Object类,当加载Obj类的时候就会报错,加载不到此类,所以需要加判断,当加载是自己包下的类是去
掉双亲,如果不是还走之前双亲逻辑)

本人工作3年中级菜鸟程序员, 最近想回顾一下知识,做了一些简单总结同时也为了自己今后复习方便,如果有逻辑
错误,大家体谅,同时也希望大牛们能给出正确答案让我改正,谢谢!
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。