JVM:class加载时机及两种显示加载的区别

来源:互联网 发布:微信做淘宝客 编辑:程序博客网 时间:2024/06/05 11:35

转载请注明出处:jiq•钦's technical Blog


从下面代码可以看出来几点:


1、 class文件的加载的时机

显示加载:

         调用ClassLoader.loadClass(className)与Class.forName(className)

隐式加载:

         创建类对象

         使用类的静态域

         创建子类对象

         使用子类的静态域

注意其实还有其他特殊的隐式加载:

在JVM启动时,BootStrapLoader会加载一些JVM自身运行所需的class

在JVM启动时,ExtClassLoader会加载指定目录下一些特殊的class

在JVM启动时,AppClassLoader会加载classpath路径下的class,以及main函数所在的类的class文件。

 

2、 两种显示加载class文件到JVM的区别

Class.forName(className)加载class的同时会初始化静态域

ClassLoader.loadClass(className)则不会初始化静态域

Class.forName借助当前调用者的class的ClassLoader完成class的加载。

 

3、 class文件的隐式加载会执行static域 

4、 JVM默认的ClassLoader是AppClassLoader 

=================================== 下面附上测试代码 =========================================

package jiq.basic;class SuperClass{public static int i = 0;public static void func(){}static {System.out.println("静态区域被执行!");}}class SubClass extends SuperClass{public static int j = 0;}public class Test {//仅仅只是作为参数或者变量出现不会载入对应的class文件SuperClass cc1 = null;public static void TestClassLoader(SuperClass vv) throws ClassNotFoundException{/** * 显示载入class并初始化静态域 * 将打印:静态区域被执行! */Class.forName("jiq.basic.SuperClass");/** * 隐式载入class并初始化静态域 * 将打印:静态区域被执行! */SuperClass c = new SuperClass();//使用关键字new创建对象SuperClass.i = 9;//使用类的静态字段SuperClass.func(); //使用类的静态方法new SubClass();//使用关键字new创建子类对象SubClass.j = 10; //使用子类的静态域/** * 仅仅只是作为参数或者变量出现不会载入对应的class文件 * 不会打印:静态区域被执行! */SuperClass cc = vv;SuperClass array[] = new SuperClass[5];/** * 调用ClassLoader的loadClass方法只会加载class文件到JVM * 并不会初始化静态区域,这就是ClassLoader.loadClass与Class.forName的区别 * 不会打印:静态区域被执行! */ClassLoader.getSystemClassLoader().loadClass("jiq.basic.SuperClass");/** * 输出为sun.misc.Launcher$AppClassLoader@2d74e4b3 * 可以看出JVM默认的类加载器ClassLoader是AppClassLoader * 而BootStrapClassLoader和ExtClassLoader都是相对较为特殊的ClassLoader */System.out.println(ClassLoader.getSystemClassLoader());}public static void main(String[] args) throws ClassNotFoundException {TestClassLoader(null);}}


1 0