00:00
那下边呢,我们来看一下这个具体的类的加载器和类的一个加载过程啊,首先呢,我们说这个从整体上进行一个了解啊,刚才我们那块也进行一个整体的一个概述了,那类加载器子系统呢,它分成三个阶段,呃,第一个呢叫做加载阶段,第二呢叫做链接阶段,第三个呢叫做诶初始化阶段啊那类加载器子系统它的整体作用是什么呢?诶这写的也非常清楚啊,就是负责从文件系统或者是网络当中来加载class文件,那class文件呢,在文件开头呢,要求有特定的标识啊,那首先呢,我们需要把这个class文件呢加载到这个内存结构当中,那加载的位置具体都有哪些呢?一会呢,我们在加载阶段的时候呢,提一下啊,那class文件呢,我们要求它有特定的一个标识,咱们之前呢,看到Java虚拟机规范里边也说明了,呃,这个class文件呢,这个任何一个这个语言都可以考虑用自己的编译器生成一个符合Java虚拟机规范的一个class文件。
01:01
然后都可以在虚拟机上进行解释执行,但是呢,要求这个class文件呢,呃,格式规范还是很严格的啊,这呢就提到一个特定的文件标识,那一会儿呢,我们也会提到这个标识呢,叫做呃cafe baby啊是一个魔术啊,这个验证的话呢,是在我们这个链接阶段的第一个叫验证阶段啊,实现的那一会我们还会具体展开来讲,那class load呢,这块说他只负责class文件的一个加载。说至于说呢,它是否能够运行则是由啊execution呃,就是我们的执行引擎来决定的啊这个事呢,怎么来理解呢?呃,我们举一个例子啊,呃,比如大家呢,在嗯这个一线城市里边工作呢,可能这个接触一情的机会都比较少啊这个过年呢,回老家,七大姑八大姨呢,都会给你介绍对象,比如这块呢,给你呃拉来了一个这个漂亮的女子是吧,然后呢,你姑呢,就诶先把你拽到旁边说呀,这个人呢,我给你带过来了,这个能不能成呢,就看你的造化了是吧,那这个时候呢,你的姑啊,七大姑八大姨就好比是这个class loader哎,他把这个人呢给你领过来了,加载到内存中了,那至于说呢,你能不能成是吧?就看你运行的本事了啊你呢,就好比是这个执行引擎,哎,就这个意思啊,那要再举一个例子的话呢,这个大家呢,应该也呃会看到一些这个综艺节目哈,这个很多综艺节目呢,都是一些普通的。
02:29
民间的一些高手,这个在舞台上说我要表演一个什么什么样的节目,嗯,他还说呢,说我得需要一些道具,好然后呢,我们会有一定的时间呢,让他准备这个道具,他准备道具呢,比如说是需要一些工作人员给他搭一些这个场景,那这些工作人员呢,就好比是这的呃,这的这个class loader,然后把这个场景呢都给他搭载完以后啊,下边的嘉宾来一句说请开始你的表演啊,那下边呢就开始表演了,那这个表演的话呢,就是具体这个演员了,就好比是这的呃执行引擎啊,那表演正常能结束,那就是挺好的,嗯,这个没问题是吧,那执行过程当中出,比如说出现这个控制人异常了,这就不算是能够正常的运行了,那就好比表演呢,出现一些失误的情况了,诶这呢主要是说的这个问题啊。
03:17
下面呢,提到说加载的类信息被存放在一块称为方法区的,呃内存空间当中,我们把这个资金码文件啊,这个资金码文件呢,我们说它是呃物理磁盘上的一个文件啊,这个咱们这个前面讲这个第一章的时候呢,也都说过这个事情啊呃编译完以后呢,生成的这个资金码文件是物理磁盘上一个文件,那这个。类的加载器呢,主要是把这个呃自己码文件呢加载到内存当中,然后呢,呃生成大的class的一个实例,嗯,这里边提到说除了这个类的本身的信息之外呢,方法区中还会存放呃运行时常量池的信息,这个运行池常量池呢,对应的是class文件中的这个常量池,咱们来理解呢,大家先有个印象啊,咱们前面的话呢,这不是针对于这个资金码文件进行过一个反编译嘛,诶大家还记不记得我们上一章中讲的哈,进行一个反编辑以后呢,我们就能够看到啊,生成的这个结构当中有一个呢,叫做哎常量池。
04:19
这个常量池里边呢,有一些具体的,呃,这个符号引用了啊,诶,那么这个常量池呢,在运行的时候呢,加载到内存里就叫做运行时常量池,哎,是这样的一个概念啊OK,行,那我们还回过来下面的话呢,我们来这个一个例子啊,再来了解一下这个类的加载器,比如说呢,我们现在有一个嗯类叫做有一个类叫car,这个编译以后呢,对应的叫car.class的自解码文件啊,保存在我们本地的硬盘上。呃,我们可以列解成呢,就好比是设计师画在纸上的一个模板一样,然后我们通过类的加载器把它呢加载到我们的内存当中,存放在方法区当中啊存放在方法区中这块呢,提到了它叫做DNA原数据模板啊,就是我们这个内存中的这个car class,我们通过这个car class呢,调用它的一个get class loader的方法,能够获取是谁加载的这个类,也就是获取到了这个加载词类的一个类的加载器,然后呢,我们可以怎么办呢?呃,在内存当中调用car这个class的构造器,或者我们叫做构造方法,构造函数都可以,哎,它呢,呃,调用构造器以后就可以创建呃几个类的对象在堆空间中,我们这有三个对象,CAR1 car2 car3,诶我们这个几个对象呢,可以认为是N个一模一样的一个实例。
05:48
啊是这样子的,当然这个一模一样,主要指的它的一些属性呢,该有的都有,方法呢,该能掉的都能掉啊,具体的一些属性值,实力变量值有可能不同啊,呃,我们通过具体的一个对象呢,调用get class这样个方法还可以获取到,呃,你是由哪个类所创建的对象啊,获取到这个类本身。
06:09
那这里边还提到了,说我们由这个自解码文件到内存中的原数据模板中间呢,用到了这个GM的类的加载器啊,此过程呢是一个运输的过程,其实呢,我们物理磁盘上的文件加载到内存中,就是以二进制流的方式加载过来的啊,流大家都比较熟悉了,呃,就是这样的一个过程啊,那具体呢,再要展开,呃,就会提到了我们讲的三部分叫加载过程,呃,链接过程和初始化的过程,这个呢,等一下咱们具体展开来说啊呃,再举一个简单的例子,大家看一下这个图。啊,这有个图,哎,我们这是一个开始,开始的话呢,我们要使用一个类,这个类呢叫做hello loader。啊,使用这个类,那这个类的话呢,我们要运行它的这个main方法啊,这个咱们直接看一下这个代码也可以哈,这个。
07:03
整体上我们讲扎逊尼的过程当中,这个代码呢,整体不会特别复杂,所以呢,这个代码呢,很多呢都提前写好了啊,我们看一下我在这儿呢,写了几个类啊,先来看一下我们目前想要演示的这个叫hello loader非常简单,这个类里边的一个main方法,里边有两句输出语句啊,说谢谢class斯加载,我说你的大恩大德,等我下边再报啊,因为呢,刚执行完它马上就结束了啊,现在呢,我做一个执行啊,Run一下。说找不到这个符号。啊,这是我们其他的这个文件中出现的这个问题,诶我呢先把这个。呃,这个类呢,我们先暂时呢,先注释一下啊。一会儿呢,咱们再考虑这个事儿。好,还回过来,我们再去做一个执行。嗯,好了,这已经出来了,那在我们刚才运行的这个过程当中,咱们的最终目的呢,是希望执行这个main方法,那这个main方法样样执行,它需要当前类来调用,那当前类有没有加载呢?呃,就遇到这个问题,那如果当前这个类no没有加载,我们需要呢,使用相应的class loader进行装载啊一会儿我们会具体讲到,那对于自定义类的话呢,实际上使用的是,呃,系统类加载器或者叫应用类加载器啊,那加载过程当中如果出现问题了,它会抛出异常。
08:31
那就相当于是加载的话呢,就看你对应的这个字节码文件。诶,咱们在这个位置呢,会有相应的这个自解码文件生成。诶,Hello loader啊,就是这个啊,这个自行码文件呢,如果不是一个合法的自行码文件,那它就会在加载的过程当中抛出异常。呃,那当然咱们这呢是呃自动的去做一个编译,然后再去运行,那所以这个加载呢,不会出现问题哈,如果有一些恶意攻击的话呢,呃,这个有可能它会对这个自解码文件呢进行一些修改,那它有可能就不合法了,那加载成功的话呢,就会在内存中啊,这个对应着有相应的一个这个这个大的class的一个结构了,然后呢,我们大的class对象了,然后我们再执行这个链接,呃,做初始化调用main方法做一个执行啊这就结束了。
09:24
这就是我们整个说的这样一个过程,大家呢先有一个印象,然后下面呢,我们具体来展开,在加载链接和初始化阶段,他们各自都做了哪些事情。
我来说两句