深入理解jvm(三):类的加载机制

一个阑风伏雨 灯火闪烁的早晨

上学期参加微软的编程之美大赛时,曾观看过一些直播视频教程,里面有一位导师讲到了“细节决定成败”时,举了个例子。他画了张图,是一匹只有一个轮廓的马,然后另一张图帮助之前那种轮廓填充了细节,图中的马立刻变得活灵活现。类似的,乔布斯也曾提过:他父亲在制作箱子时总是把箱子内侧做得和外侧一样偏亮,所以在设计mac时,我也要保证他的内部一样的井然有序。《史记陈涉》中也提过:若为庸耕,何为富贵。好多人可能画了一辈子的马的轮廓,做了一辈子外观漂亮的箱子,但是这些东西有千千万万人在做,多你一个不多,少你一个不少。也许这就是这个世界上有那么多的程序员,却少有it精英的原因。

在类的加载机制之前一章,是类的文件结构。它简述了java文件经过编译得到的Class源文件中,每个进制位与原程序的一一对应关系。内容繁琐且乱,不做blog了。

将类的class文件加载到内存并进行校验,解析和初始化的过程就是类的加载过程

加载的时机

主动引用触发加载包括:使用new,getstatic,putstatic,invokestatic字节码/使用反射/初始化的子类有未被加载的父类/执行主类优先加载/使用jdk7的动态语言支持

被动引用不会加载,包括:子类引用父类的静态字段/通过数组来定义引用类/访问类的静态变量。

类的加载过程

加载

通过一个类的全限定名来获取此类的二进制字节码(这个过程灵活度很高,可以从zip中获得,从网络中获得,动态代理中获得,其他文件如jsp生成,从数据库忠获得),将这个字节流所代表的静态存储结构转化为运行时数据结构,在堆中生成这个类的对象,作为这个类方法区各种数据的访问入口。

验证

文件格式验证:保证输入的字节流能被正确的解析并储存于方法区

元数据验证:语义校验

字节码验证:数据流和控制流的验证。(tip:不能保证百分之百的正确,因为停机原理)

符号引用验证

additiona:验证过程是重要的,但不是必要的。减少一些标准类库类的验证过程可以提高程序的运行效率。

准备

为类变量赋默认值

解析

解析的过程就是将符号引用转换为直接引用的过程。

符号引用和直接引用的区别:直接引用是一个直接指向目标的指针,相对偏移量和句柄。它与内存布局相关。不同的虚拟机执行解析后得到的直接引用不同。直接引用指向的目标一定已经存在于内存中。符号引用刚好相反。

1.类和接口的解析:根据类和接口是不是数组类型区分为对对象(包括对象数组)的验证和对数组的验证

2.字段的解析:查找类本身是否包含简单名称和字段描述都相符的字段,若无,则搜索父接口,若无继续搜索继承的父类,若搜索至Object类也是无,则抛出NoSuchFeildEorro异常

3.类方法解析:首先如果类方法查找的类是接口,直接抛出IncompatibleClassException异常,否则按照类似字段解析的过程进行类方法解析

4.接口方法解析:与类方法解析类似

初始化

初始化阶段就是执行构造器的()方法,这个方法由编译器自动收集所有类变量的赋值动作和静态语句块合并而成。它的执性顺序是先父类后子类,且它是线程安全的。

类加载器

类和类加载器确立了一个类的唯一性。

类加载器包括三个层级:启动加载器,扩展加载器,系统加载器。用户可以通过重写Classload()和findClass()方法构建自己的类加载器。

双亲委派模型

双亲委派模型是指处于该模型下的一个类要求加载时,总是请求它的父加载器先进行加载,只有在他的父加载器无法加载的情况下,才启动子加载器进行加载。优势:java的类随着它的加载器有一种层次的优先级关系

破坏双亲委派模型的情况

1.jdk1.2之前还没有出现双亲委派模型之前(其实,逻辑上来讲:既然没出现那么破坏就无从谈起),所以严格来讲,应该是双亲委派模型引入jdk与之前的已存在的类加载器不兼容,故而出现了findclass()来兼容双亲委派模型(findclass()让类先调用父类加载器,在父类加载器加载不了的情况下再调用findclass()的加载逻辑)

2.JNDI JDBC JCE等服务。启动类加载器调用了普通类加载器才能加载的接口。解决办法:线程上下文

3.代码热替换的相关技术,OSCi等。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值