Java内存
-
堆
-
存放new对象和数组 -
可以被所有线程共享,不会存放别的对象的引用
-
栈
-
存放基本变量类型(会包含这个基本类型的具体数值) -
引用对象的变量(会存放引用在堆中的具体地址)
-
方法区
-
可以被所有线程共享 -
包含了所有的class和static变量
类的加载过程
当程序主动使用某个类时,如果该类还没有加载到内存中,此时系统会通过三个步骤来对该类进行初始化:
类的加载 ---> 类的链接 ---> 类的初始化
① 类的加载(Load) : 将类的文件读取到内存中,并创建一个java.lanf.Class对象,这个过程是由类加载器完成的。
② 类的链接(Link) : 将类的二进制文件数据合并到 JRE (Java Runtime Environment) 中。
③ 类的初始化(Initialize):JVM(Java Virtual Machine)对类进行初始化。
详细说明
package Learning;
public class Test {
public static void main(String[] args) {
Loading loading = new Loading();
System.out.println(loading.i);
}
}
class Loading{
static int i = 1;
static {
System.out.println("静态代码块 - Loading");
i = 2;
}
public Loading(){
System.out.println("无参构造 - Loading");
}
}
测试结果:
静态代码块 - Loading
无参构造 - Loading
2
?过程分析
图示:
?Test类写好后,会编译成Class文件,加载类的信息到内存中
类有哪些信息?
加载这些信息的时会在堆中生成 Java.lang.Class对象也就是类对应的Class对象,每个类只有唯一一个Class对象!
加载完这些信息后,程序就会执行main( )方法,并且这时候将静态变量 i 初始化为 0(链接阶段)
然后会在堆中进行new Loading( )操作,产生Loading类的对象,Loading类的对象会指向方法区中 Loading类中的数据,Loading类的对象会去找Loading类对应的唯一的Class对象,从Loading类对应的唯一的Class对象中得到数据,通过得到的这些数据,开始给Loading类显式赋值,最后开始初始化,Loading类调用了一个方法,这个方法是<clinit>( )方法:
<clinit>(){
i = 1;
System.out.out.println("静态代码块 - Loading");
i = 2;
}
将静态代码块中的初始值都合并起来,由于静态代码块是按照顺序执行,i 的值被覆盖,最后结果是 i = 2。
|