JVM之Class加载过程
1.class进入内存有三大步
第一步:Loading:是把一个class文件load内存装到内存里去,他本来是是class文件上的一
个一个的二进制,一个一个的字节,装完之后就是接下来Linking。
第二步:Linking:Linking又分为三小步,第一小步Verification,第二小步Preparation,第三小步Resolution。Verification是校验装进来的class文件是不是符合class文件的标准,假如你装进来的不是这个CA FE BA BE,在这步骤就被拒掉了。Preparation是把class文件静态变量赋默认值,不是赋初始值,比如你static int i = 8,注意在这个步骤8并不是在把i值赋成8,而是先赋成0。Resolution是把class文件常量池里面用到的符号引用,要给它转换为直接内存地址,直接可以访问到的内容。
第三步:Initlalizing:调用类初始化代码,给静态成员变量赋初始值,意思是静态变量这时候赋值才成为初始值
2.class加载双亲委派机制
Bootstrap:最顶层的是类加载器,他是来加载lib里jdk最核心的的内容比如说rt.jar charset.jar等核心类。所以说什么时候我调用getClassLoader()拿到这个加载器的结果是一个空值的时候代表的你已经到达了最顶层的加载器。
Extension:加载器扩展类,加载扩展包里的各种各样文件,这些扩展包在jdk安装目录jre/lib/ext下的jar。
APP:这个就是平时用的加载器application,他用于加载classpath指定的内容。
CustomClassLoader:这个就是自定义加载器ClassLoader,加载自己自定义的加载器。
CustomClassLoader父类加载器是>application父类加载器是>Extension父类加载器是>Bootstrap 。切记他们之间不是继承关系,只是语法上的继承。
一个class文件需要被load内存时候是这样的:任何一个class,加入你自定义了ClassLoader,这是时候就先尝试去自定义里面找,他内部维护着缓存,说你有没有已经帮我加载进来了,如果加载进来一遍就不需要加载第二遍,如果没加载进来,就赶紧把我加载进来。他如果没有在自己的自定义缓存没找到的话,他并不是直接加载这块内存,他会去他的父亲application父加载器,说爸爸你有没有把这个类加载进来啊,这时候他就会去他的缓存里面找有没有这个类啊,如果有返回,如果没有委托给他的父亲Extension,如果有返回,如果没有委托给他的父亲Bootstrap ,有就返回,如果都没有就往回在委托Extension我这没有你去加载,Extension说我只负责我扩展jar包部分,你的类我找不到啊,那麻烦application去加载,application说我只负责加载classpath指定内容啊,其他的我不知道找不到,然后委托ClassLoader去找,整个过程是经过了一圈转了一圈,才真正把这个类加载进来,当我们能够把这个类加载进来的时候叫做成功,如果加载不进来,抛异常ClassNoffound找不到,这就叫做双亲委派。
为什么要搞双亲委派?
主要是为了安全,加入用反正法,如果任何一个class都可以把它load内存的话,那我就可以给你java.lang.string,我交给自定义ClassLoader,把这个stringload进内存,打包给客户,然后把密码存储成string类型对象,我可以偷偷摸摸的把密码发给我自己,那就不安全了。双亲委派的就不会出现过这样,自定义ClassLoader加载一个java.lang.string他就产生了警惕,他先去上面查有没有加载过,上面有加载过直接返回给你,不给你重新加载。
类:class -----> load----->默认值---->初始值
new对象:new----->申请内存----->默认值------>初始值
这就是为啥双重校验单列模式加volatile关键字的原因,如果不加的话会发生这样一个情况:第一个线程加上锁,检查完了其他线程没有初始化然后我加锁上锁,上锁完对这个INSTANCE进行初始化,可是很不幸的是如果这个初始化过程初始化到一半的时候,什么叫一半,就是我们new了这个对象并且还申请了内存,申请完内存里面的成员变量假如说有一个值还给它赋了一个初始值为0,到这个情况下,这个时候的INSTANCE就已经指向内存了,所以这个INSTANCE已经不等于空了,这种情况下另外一个线程来了,他来了之后后他会首先执行这句if(INSTANCE == null),很不幸这时候它还是空值吗,不是了,他是处于半初始化状态。那我第二个线程就直接开始用这个初始值了,而不是用那个默认值。解决这个问题的关键就是加上volatile。