[size=medium]Java 虚拟机类装载体系 [/size]
装载:把二进制形式的java类型读入Java虚拟机中通过该类型的完全限定名,产生一个代表该类型的二进制数据流。解析这个二进制数据流为方法区的内部数据结构。在堆上创建一个表示该类型的java.lang.Class类的实例。
1、何时装载
(1)隐式装载 package test; Public class A{ public void static main(String args[]){ B b = new B(); } } class B{C c;} class C{}
A、B、C类装载顺序:A 、B (C不装载)
(2)显示装载 A、使用Class类的forName方法。它可以指定装载器,也可以使用装载当前类的装载器。例如: Class.forName("test.A"); B、使用类路径类装载装载. ClassLoader.getSystemClassLoader().loadClass("test.A"); C、使用当前进程上下文的使用的类装载器进行装载,这种装载类的方法常常被有着复杂类装载体系结构的系统所使用。 Thread.currentThread().getContextClassLoader().loadClass(“test.A”) D、使用自定义的类装载器装载类 public class MyClassLoader extends URLClassLoader{ public MyClassLoader() { super(new URL[0]); } } MyClassLoader myClassLoader = new MyClassLoader(); myClassLoader.loadClass("test.A");
2、谁来装载——java虚拟机的三个类加载器
A、Bootstrap ClassLoader 根类加载器 负责加载Java的核心类。
B、Extension Classloader 扩展类加载器 负责加载JRE扩展目录中JAR的类包。(可以为Java扩展核心类以外的新功能)
C、System Classloader 系统(应用)类加载器 负责加载CLASSPATH环境变量所指定的JAR包和类路径
3、类加载机制
(1)全盘负责:即一个类加载器负责加载某个Class的时候,该Class所依赖的和引用的其它Class也将由类加载器负责,除非显示的使用另外一个类加载器业载入。
(2)父类委托:先让父类加载器加载该Class,只有在父类加载器无法加载该类时,行尝试从自己的类路径中加载该类。
(3)缓冲机制:被加载过的Class都会被缓存,当需要这个Class时,类加载器就会到缓存中搜索Class,如果不存在该Class对象,系统会重新读取该类对应的二进制文件,并转换成Class对象,再放入缓存。
这就是为什么我们修改了Class后,程序必须重新启动JVM,程序所作的修改才会生效的原因;
4、类的初始化时机
一个类经过加载-连接之后就是进行它的初始化;
当Java程序首次通过下面6种方式使用某个类或者接口时,系统就会初始化该类或接口
a, 创建类的实例。new 关键字,或反射创建实例,反序列化创建实例;
b, 调用某个类的静态方法。
c, 访问某个类或接口的静态属性,或为该静态属性赋值。
d, 使用反射强制创建某个类或接口对应的java.lang.Class对象。如,Class.forName(“Person”),如果系统还未初始化Person,那么Person就会被初始化;
e, 初始化某个类的子类时,该类的所有父类都会被初始化;
f , 直接使用java.exe命令来运行某个主类,程序会先初始化该主类;
5、类加载Class的大致步骤
①检测Class是否已加载,已加载则进行第8步,否则进行第2步;②如果父加载器不存在则进行第4步,存在则进行第3步;③ 请求父加载器加载该类,成功则进入第8步,不成功则进行第5步;④请求根加载器载入,成功则进入第8步,不成功则进行第7步;⑤寻找Class文件(从与此ClassLoader相关的类路径中寻找),找到则执行第6步,找不到则执行第7步;⑥从文件中载入Class,成功载入后进入第8步;⑦抛出ClassNotFoundException⑧返回Class
装载:把二进制形式的java类型读入Java虚拟机中通过该类型的完全限定名,产生一个代表该类型的二进制数据流。解析这个二进制数据流为方法区的内部数据结构。在堆上创建一个表示该类型的java.lang.Class类的实例。
1、何时装载
(1)隐式装载 package test; Public class A{ public void static main(String args[]){ B b = new B(); } } class B{C c;} class C{}
A、B、C类装载顺序:A 、B (C不装载)
(2)显示装载 A、使用Class类的forName方法。它可以指定装载器,也可以使用装载当前类的装载器。例如: Class.forName("test.A"); B、使用类路径类装载装载. ClassLoader.getSystemClassLoader().loadClass("test.A"); C、使用当前进程上下文的使用的类装载器进行装载,这种装载类的方法常常被有着复杂类装载体系结构的系统所使用。 Thread.currentThread().getContextClassLoader().loadClass(“test.A”) D、使用自定义的类装载器装载类 public class MyClassLoader extends URLClassLoader{ public MyClassLoader() { super(new URL[0]); } } MyClassLoader myClassLoader = new MyClassLoader(); myClassLoader.loadClass("test.A");
2、谁来装载——java虚拟机的三个类加载器
A、Bootstrap ClassLoader 根类加载器 负责加载Java的核心类。
B、Extension Classloader 扩展类加载器 负责加载JRE扩展目录中JAR的类包。(可以为Java扩展核心类以外的新功能)
C、System Classloader 系统(应用)类加载器 负责加载CLASSPATH环境变量所指定的JAR包和类路径
3、类加载机制
(1)全盘负责:即一个类加载器负责加载某个Class的时候,该Class所依赖的和引用的其它Class也将由类加载器负责,除非显示的使用另外一个类加载器业载入。
(2)父类委托:先让父类加载器加载该Class,只有在父类加载器无法加载该类时,行尝试从自己的类路径中加载该类。
(3)缓冲机制:被加载过的Class都会被缓存,当需要这个Class时,类加载器就会到缓存中搜索Class,如果不存在该Class对象,系统会重新读取该类对应的二进制文件,并转换成Class对象,再放入缓存。
这就是为什么我们修改了Class后,程序必须重新启动JVM,程序所作的修改才会生效的原因;
4、类的初始化时机
一个类经过加载-连接之后就是进行它的初始化;
当Java程序首次通过下面6种方式使用某个类或者接口时,系统就会初始化该类或接口
a, 创建类的实例。new 关键字,或反射创建实例,反序列化创建实例;
b, 调用某个类的静态方法。
c, 访问某个类或接口的静态属性,或为该静态属性赋值。
d, 使用反射强制创建某个类或接口对应的java.lang.Class对象。如,Class.forName(“Person”),如果系统还未初始化Person,那么Person就会被初始化;
e, 初始化某个类的子类时,该类的所有父类都会被初始化;
f , 直接使用java.exe命令来运行某个主类,程序会先初始化该主类;
5、类加载Class的大致步骤
①检测Class是否已加载,已加载则进行第8步,否则进行第2步;②如果父加载器不存在则进行第4步,存在则进行第3步;③ 请求父加载器加载该类,成功则进入第8步,不成功则进行第5步;④请求根加载器载入,成功则进入第8步,不成功则进行第7步;⑤寻找Class文件(从与此ClassLoader相关的类路径中寻找),找到则执行第6步,找不到则执行第7步;⑥从文件中载入Class,成功载入后进入第8步;⑦抛出ClassNotFoundException⑧返回Class