我们学习Java必定知道对象,通过对象拿取变量和方法。但是,Java虚拟机(简称:JVM,全称:Java Virtual Machine)到底是怎么准确拿到这些东西的呢?首先,我们了解一下Java虚拟机,Java虚拟机包括一套字节码指令集、一组寄存器、一个栈、一个垃圾回收堆和一个存储方法域。
一个完整的Java程序运行过程中JVM会为我们分配以下内存空间:
1、寄存器:JVM内部虚拟寄存器,存储速度非常快,程序不可控制。
2、栈内存:保存局部变量的值,包括“基本数据类型的值”、“类的实例”等。 程序编译时对数据区的需求时未知的,只有在运行时才能够知道,但是规定在运行中进入一个程序模块时,必须知道该程序模块所需的数据区大小,所以栈式存储分配按照"先进后出"的原则进行分配。
3、堆内存:用来存放动态产生的数据,比如new出来的对象。堆式存储分配则专门负责在编译时或运行时模块入口处都无法确定存储要求的数据结构的内存分配,,比如可变长度串和对象实例。堆由大片的可利用块或空闲块组成,堆中的内存可以按照任意顺序分配和释放。(注意:创建出来的对象只包含属于各自的成员变量,并不包含成员方法。因为同一个类的对象拥有各自的成员变量,存储在各自的堆中,他们只是共享该类的方法。例如:Test num1 = new Test()和Test num2 = new Test()中,num1 != num2)
4、静态存储区:存放静态变量的内存区域。程序在编译时就给静态变量分配固定的内存空间,这种分配策略要求程序代码中不允许有可变数据结构(比如可变数组)、嵌套或递归结构。因为他们都会导致编译程序无法准确计算存储空间需求。
5、常量存储区:存放final的常量变量,注意,String类型的对象都是常量,系统维护了一个String的常量池。
6、其他存储:非RAM存储器,主要就是磁带、磁盘等等。
在堆中分配的java内存,有java虚拟机的自动垃圾回收管理器来管理。
在堆中产生了一个数组或对象后,还可以在栈中定义一个变量,让变量的值等于数组或对象在堆中的首地址,于是变量就成了数组或对象的引用变量,以后就可以在程序中使用栈中的引用变量来访问堆中的数组或对象。