一、 加载
“加载” 是 “类加载”过程的一个阶段。在加载阶段,虚拟机完成了一下3件事情。
1. 通过一个类的全额限定名来获取定义此类的二进制字节流。
2. 将这个字节流所代表的静态存储结构转化转化为方法区的运行时数据结构。
3. 在内存中创建一个java.lang.Class对象,作为方法区该类的各种数据的访问入口。
二、 二进制流的来源
“通过一个类的全额限定名来获取定义此类的二进制字节流”这条,没有指定要从哪里获取、怎样获取二进制流。让充满创造力的开发者在这个平台上玩出各种花样。
例如:
1. 从zip中读取,这个一点很常见的,最终成为 jar、ear、war 这些格式的基础。
2. 从网络中获取。
3. 运行时计算生成, 这里应用最多的场景是 动态代理技术。
4. 由其他文件生成,典型的场景就是jsp文件。
5. 从数据库中读取。
......
三、 数组加载等注意事项
1. 非数组类的加载阶段(准确的说是获取二进制字节流的阶段)
这个阶段是开发人员具有很高的可控性,可以使用系统提供的引导类的加载器,也可以使用用户自定义的类加载器。
2. 数组类加载阶段
数组类的加载阶段和非数据类还是有些不同的,但是他们有着千丝万缕的联系。毕竟数组的元素类型最终要是要通过类加载器加载。一个数组类的创建过程怎讯一下规则:
(1) 数组的组件类型是引用类型
递归采用本节定义的加载过程加载该组件类型,数组会 在加载该组件类型的类加载器的类名称空间上增加一个标识。
(2) 数组的组件类型是非引用类型
虚拟机会把数组标记为与引导类加载器关联。
(3) 可见性
数组的可见性与组件类型的可见性是一致的,如果是基本类型的数组,默认是public的。
3. 注意
(1) 在内存中创建一个 java.lang.Class的对象, 虚拟机规范中并没有规定这个对象保存在哪里。
(2) 在hotspot中,java.lang.Class的对象比较特殊,虽然是对象,却保存在访法区中。
(3) 加载阶段和连接阶段是交叉进行的,交叉阶段还没有完成的时候,连接阶段也许已经开始。但是两个阶段的开始时间的顺序是确定的。
4.加载器
来自http://blog.csdn.net/cutesource/article/details/5904501
JVM的类加载是通过ClassLoader及其子类来完成的,类的层次关系和加载顺序可以由下图来描述:
1)Bootstrap ClassLoader
负责加载$JAVA_HOME中jre/lib/rt.jar里所有的class,由C++实现,不是ClassLoader子类
2)Extension ClassLoader
负责加载java平台中扩展功能的一些jar包,包括$JAVA_HOME中jre/lib/*.jar或-Djava.ext.dirs指定目录下的jar包
3)App ClassLoader
负责记载classpath中指定的jar包及目录中class
4)Custom ClassLoader
属于应用程序根据自身需要自定义的ClassLoader,如tomcat、jboss都会根据j2ee规范自行实现ClassLoader
加载过程中会先检查类是否被已加载,检查顺序是自底向上,从Custom ClassLoader到BootStrap ClassLoader逐层检查,只要某个classloader已加载就视为已加载此类,保证此类只所有ClassLoader加载一次。而加载的顺序是自顶向下,也就是由上层来逐层尝试加载此类。