JVM-01-JVM类加载

144 阅读3分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第1天,点击查看活动详情

JVM类加载过程

如果我们要去生产一件物品,我们需要经历几个步骤,比如我们需要知道我们要做的东西是什么,这个东西到底符不符合生产的规范等等。其实JVM类加载在整个对象从生产到最后回收仅仅是第一步,它对一个对象有了一个定义,只是从最基本的字节码的定义上升到了JVM层面的定义。

加载

首先,我们需要通过磁盘IO找到定义这个类的字节码文件,并且把该字节码文件变成方法区的运行时数据结构,最后在堆中生成一个Class对象作为访问方法区的入口。

在加载时就涉及到了大名鼎鼎的双亲委派模型。

双亲委派模型

在加载过程中,我们需要通过类加载器去完成加载过程,并且类加载器不仅仅只有一个,系统为我们提供了三种类加载器,需要注意的是他们之间其实并没有继承关系,只是在类加载器内部有一个parent属性,去帮助完成双亲委派过程。

  1. App ClassLoader:主要是加载Java核心库
  2. Ext ClassLoader:主要是加载Java拓展库
  3. BootStrap ClassLoader:一般Java应用的类都是由它来加载

以上三个是由JVM提供的三种类加载器,在加载某一个类时,类加载器不会收到这个类信息马上去进行加载,会把加载任务交给自己的父亲,也就是说最顶层的App ClassLoader会收到所有类加载的请求,当自己无法加载时再返回给自己的儿子进行加载。

当然了,有人会说这样子加载不会很浪费时间吗,明明一个类加载器就可以完成的任务为什么需要分成三个,JVM这样子设计其实有两个好处。

第一个好处就是可以防止Java核心的类库被修改,如果Java有一个String类,我们自己再定义一个String类,那未来其他类去使用的话就乱套了。

第二个好处是也防止了某些类被重复加载,如果父亲加载了那儿子就不用再加载了。

当然这一种模型并不是不可打破的,如果我们自己写一个类加载器,继承类加载器的父类,再重写LoadClass方法就可以打破。并且在某种情况下这种打破是必须的,比如TomCat打破双亲委派模型,就是为了同一个TomCat中部署不一样的项目时,不同的项目间可能会有同名的类,或者可能会引用同一个类库中的不同版本,那么打破双亲委派原则,不同的WebApp间实现隔离就非常重要了。

验证

这一步通常是和上一步一起发生的,主要是校验字节码文件的正确性,比如CAFEBABY,是否符合字节码文件标准等。

准备

类变量(static)将在这一步赋初始值(0值),不包括势力变量,同时也会为static final变量初始化,因为这种变量不会再发生改变。

解析

这一步是将符号引用解析为直接引用,得到类或者字段在内存中的指针或偏移量。

初始化

最后一步将会根据程序员的主观设置去对类变量赋初始值,通过类构造器<client>()方法

总结

这一篇是整个JVM系列的开始,也是一个对象创建开始的地方,以后发生的许多故事都将从这里开始。同时这也是我的第一篇博客,梦开始的地方...希望能够坚持下去。