1、编译与类加载
类的编译是什么?就是从.java到.class的过程,很简单
类的加载是什么?下面是《深度理解java虚拟机》的原文
在加载阶段,Java虚拟机需要完成以下三件事情:
1)通过一个类的全限定名来获取定义此类的二进制字节流。
2)将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构。
3)在内存中生成一个代表这个类的java.lang.Class对象,作为方法区这个类的各种数据的访问入 口。
简单一点来讲,就是虚拟机需要将编译得到的class文件装载到jvm中,并在内存中得到一个该类对应的Class对象,方便之后用new关键字得到该类的对象。
2、什么是类加载器?
Java虚拟机设计团队有意把类加载阶段中的“通过一个类的全限定名来获取描述该类的二进制字节 流”这个动作放到Java虚拟机外部去实现,以便让应用程序自己决定如何去获取所需的类。实现这个动 作的代码被称为“类加载器”
说简单一点,就是将类加载一定需要类加载器,类加载器并不在虚拟机内,而是在虚拟机外部。
3、双亲委派模型
JDK 1.2以来,Java一直保持着三层类加载器、双亲委派的类加载架构,尽管这套架构在Java模块化系统出现后有了一些调整变 动,但依然未改变其主体结构。
所谓三成类加载器,即启动类加载器,扩展类加载器,应用程序类加载器。不同的类加载器分别加载不同范围的jar包。
启动类加载器处于金字塔的顶端,用于加载java核心类库的加载。扫描包的范围是javahome/lib下的jar包
扩展类加载器则在下面一点,扫描Java home/lib/ext下的jar包和class文件。
应用程序类加载器则在更下面一点,扫面ClassPath下的jar包和.class文件。
了解了三层类加载器后,就可以尝试理解双亲委派模型了。
其实很简单,当一个类想要加载时,会从金字塔塔底开始,哪怕塔底的类加载器可以完成任务,也要往塔顶移动,所以类加载需求最后都会到达塔顶,当塔顶元素处理不了后,再一级一级的往下走,直达找到一层可以完成任务的类加载器,原文如下:
双亲委派模型的工作过程是:如果一个类加载器收到了类加载的请求,它首先不会自己去尝试加 载这个类,而是把这个请求委派给父类加载器去完成,每一个层次的类加载器都是如此,因此所有的 加载请求最终都应该传送到最顶层的启动类加载器中,只有当父加载器反馈自己无法完成这个加载请 求(它的搜索范围中没有找到所需的类)时,子加载器才会尝试自己去完成加载。
4、优缺点
双亲委派模型的优点是:
1、Java中的类随着它的类 加载器一起具备了一种带有优先级的层次关系。
2、可以避免类的重复加载导致程序混乱
怎么理解呢,其实很简单,举个例子,如果你在本地程序上写一个java.lang.String的类,是否会在类加载过程中导致你写的String类会作用在代码上,而没有使用Java中自带的String类呢?结果是不会的,为什么呢,因为双亲委派机制使得当有String类加载需求时,会一层一层的向上传递到达塔顶,塔顶中也有String,就会直接塔顶完成该类加载操作,所以塔顶负责Java核心类的加载,这一机制使得,无论你在ClassPath上怎么新建java.lang.String,都不会对核心类中的String有所影响。
当然,由于一级一级向上传递,自然也就避免重复加载的问题。