Java内存:1.堆:存放new的对象和数组;可以被所有线程共享,不会存放别的对象引用
2.栈:存放基本变量类型(会包含这个基本类型的具体数值);存放对象的变量(会存放这个引用在堆里面的具体地址)
3.方法区:可以被所有线程共享;包含了所有的class和static变量
当程序主动使用某个类时,如果该类还未被加载到内存中,则系统会通过如下三个步骤来对该类进行初始化:
1.类的加载:将类的class文件读入内存,并为之创建一个java.lang.Class对象,此过程由类加载器完成
2.类的连接:将类的二进制数据合并到JRE中
验证:确保加载的类信息符合JVM规范,没有安全方面的问题
准备:正式为类变量(static)分配内存并设置类变量默认初始值的阶段,这些内存都将在方法区进行分配
解析:虚拟机常量池内的符号引用(常量名)替换为直接引用(地址)的过程
3.类的初始化:JVM负责对类进行初始化
执行类构造器<clinit>()方法的过程。类构造器<clinit>()方法是由编译期自动收集类中所有类变量的赋值动作和静态代码块中的语句合并产生的。(类构造器是构造类信息的,不是构造该类对象的构造器)
当初始化一个类的时候,如果发现其父类还没有进行初始化,则需要先触发父类的初始化
虚拟机会保证一个类的<clinit>()方法在多线程环境中被正确加锁和同步
例如:
1 public class test { 2 public static void main(String[] args) { 3 System.out.println(A.m); 4 } 5 } 6 7 class A { 8 static int m = 100; 9 10 static { 11 m = 300; 12 } 13 14 public A() { 15 16 } 17 }
以上代码输出300而非100