JAVA的内存大致分为5块:方法区,堆,JAVA栈,PC寄存器,本地方法栈。(详见深入JAVA虚拟机一书)
1.本地方法栈:调用本地方法时可能会用到的数据区
2.PC寄存器:就是程序计数器,装的是地址,总是指向对应线程的下一条指令。
3.方法区:
1》.存储类型信息,比如类或者接口的全限定名,权限修饰符等。
2》.字段信息:字段名,类型,修饰符
3》.静态变量信息(不包含常量):编译时常量在连接时已经被替换了。
4》.方法信息:除了定义信息外,还有方法体,异常表,栈帧局部变量去的大小;操作数栈(不知啥玩意)
5》.常量池:该类型所用到的常量的有序集合(看不懂在说啥),包括对其他字段,类型,方法的符号引用(引用不是变量吗????)。
6》.方法表:主要是为了快速的调用方法。
还有指向类Class的引用,指向Class对象的引用,指向ClassLoader的引用
4.堆:包括句柄池和对象池
5.栈
在 程序运行使用到某个类时,如果这个类没有被预先加载,就会执行加载,链接,初始化的动作。
虚拟机首先把.class文件读入内存,并创建相应的java.lang.Class对象.然后进入连接状态,对类进行验证,a:抽取信息到方法区,相应的在方法区
也就给类变量分配空间,以默认值默认初始化,接着把在定义类变量时指定的值赋给类变量,执行静态代码块,类的初始化完成(绿色字体:这个过程可能不是这样,这是我自己的理解,不过最后的内存状态是一样的)。比如(Person p=new Person("zhangsan",14)),这里它是个被调用类,在main方法中的第一句,在调用类(设它为A)里,在main方法执行到时,虚拟机相应的检查A的常量池,发现常量池的第一条是个引用p,然后到A的方法区找Person类数据,没找到就加载,链接,初始化。然后把p放到栈中,在常量池p的位置放入指向Person类型数据结构的指针,然后调用new操作符,在堆的对象池内以默认值给Person对象分配内存,如果在定义时有指定值,赋给,在句柄池中保存指向方法区和对象池的指针,接着查找并调用构造函数,在栈中建立两个局部变量,运算完成后,结果复制到Person对象中,把引用p指向句柄池。
|