为何研究类加载全过程?java
类加载机制数组
例1:安全
public class Demo01 { public static void main(String[] args) { A a = new A(); System.out.println(a.width); } } class A{ public static int width=100; //静态变量,静态域 field static{ System.out.println("静态初始化类A"); width = 300 ; } public A() { System.out.println("建立A类的对象"); } }
分析:数据结构
说明:多线程
内存中存在栈、堆(放建立好的对象)、方法区(实际也是一种特殊堆)spa
1、JVM加载Demo01时候,首先在方法区中造成Demo01类对应静态数据(类变量、类方法、代码…),同时在堆里面也会造成java.lang.Class对象(反射对象),表明Demo01类,经过对象能够访问到类二进制结构。而后加载变量A类信息,同时也会在堆里面造成a对象,表明A类。线程
2、main方法执行时会在栈里面造成main方法栈帧,一个方法对应一个栈帧。若是main方法调用了别的方法,会在栈里面挨个往里压,main方法里面有个局部变量A类型的a,一开始a值为null,经过new调用类A的构造器,栈里面生成A()方法同时堆里面生成A对象,而后把A对象地址付给栈中的a,此时a拥有A对象地址。code
3、当调用A.width时,调用方法区数据。对象
当类被引用的加载,类只会加载一次blog
例2:
public class Demo01 { static{ System.out.println("静态初始化Demo01"); } public static void main(String[] args) throws Exception { System.out.println("Demo01的main方法!"); System.out.println(System.getProperty("java.class.path")); //主动引用 // new A(); // System.out.println(A.width); // Class.forName("com.sinosoft.test.A"); //被动引用 // System.out.println(A.MAX); // A[] as = new A[10]; System.out.println(B.width);//B类不会被加载 } } class B extends A { static { System.out.println("静态初始化B"); } } class A extends A_Father { public static int width=100; //静态变量,静态域 field public static final int MAX=100; static { System.out.println("静态初始化类A"); width=300; } public A(){ System.out.println("建立A类的对象"); } } class A_Father extends Object { static { System.out.println("静态初始化A_Father"); } }