1. blog learning .... 深入探讨 Java 类加载器
jdk 1.6 写道
Class
类的实例表示正在运行的 Java 应用程序中的类和接口。
2011-10-1 update
以下命令可以查看,JVM是如何将二进制文件(*.class)载入内存的。
java -verbose ABClient
测试代码:
public class A{ public void printInfo(){ System.out.println(" class A printInfo..."); } } public class B{ public void printInfo(){ System.out.println(" class B printInfo..."); } } public class ABClient{ public void printInfo(){ System.out.println(" class ABClient printInfo..."); } public static void main(String args[]){ new A().printInfo(); //只有new 出是实例的时候 ,才会被load 进 内存中。声明则不会。 B b; } }
结果:
[Loaded java.security.cert.Certificate from shared objects file] [Loaded ABClient from file:/E:/coding/20111001_java/classLoader/] ---------static block code loader finished------------ [Loaded A from file:/E:/coding/20111001_java/classLoader/] class A printInfo... [Loaded java.util.AbstractList$Itr from shared objects file]
###初始化对象的3种方法:
为ABClient类添加静态代码块:
static{ System.out.println("========run static code========"); }
public class InstanceObject{ public void printTest(String info){ System.out.println("----------run----------:" + info); } public static void main(String args[]){ // 隐式 实例化方法 InstanceObject io = new InstanceObject(); io.printTest("隐式实例化"); //显式 实例化方法 //1 Class.forName try{ Class clazz = Class.forName("InstanceObject"); InstanceObject io2 = (InstanceObject)clazz.newInstance(); io2.printTest("显式实例化 forName"); }catch(java.lang.InstantiationException ie){ ie.printStackTrace(); }catch(java.lang.ClassNotFoundException cnfe){ cnfe.printStackTrace(); }catch(java.lang.IllegalAccessException iae){ iae.printStackTrace(); } //2 ClassLoader try{ ClassLoader clazzLoader = InstanceObject.class.getClassLoader(); System.out.println("begin to load the ABClient class"); Class clazz2 = clazzLoader.loadClass("ABClient"); //静态区域块 是在第一次实例化时才被载入的。 System.out.println("begin to instance the ABClient object"); ABClient abObject = (ABClient)clazz2.newInstance(); }catch(java.lang.InstantiationException ie){ ie.printStackTrace(); }catch(java.lang.ClassNotFoundException cnfe){ cnfe.printStackTrace(); }catch(java.lang.IllegalAccessException iae){ iae.printStackTrace(); } //API中 获取 Class 实体的方法有2种, 推荐使用 类名.class ;另外一种是instance.getClass() } }
测试Class.forName 第二个参数为 true or false时的 载入静态代码块的区别。
测试结果为 无论是true还是false,对象实例化之后静态代码块还是没有被执行,在实例调用某个方法后才执行。这点有待验证。
至于 classLoader 载入.class文件后,静态代码块不会被执行;初始化(newInstance)后,静态代码块被执行,且仅执行一次。