JVM的内存分配主要基于两种,堆和栈。
我们来看一下java程序运行时候的内存分配策略:
1):静态存储区(方法区);
2):栈区;
3):堆区;
1):主要存放静态数据,全局static数据和常量。
2):在java中,栈的分配是和线程绑定在一起的,当我们创建一个线程的时候,很显然,JVM就会为这个线程创建一个java栈,一个线程的方法的调用和返回对应于这个java栈的压栈和出栈。当线程激活一个java方法时,JVM就会线程的java堆栈里新压入一个帧,这个帧自然成了当前帧。在此方法执行期间,这个帧用来保存参数,局部变量,中间计算过程和其他数据。
栈中主要存放一些基本类型的变量数据(int,short,long,byte,float,double,boolean,char)和对象的句柄(引用)。方法体内的局部变量都在栈上创建的。
优点:存取速度比堆快,仅次于寄存器,栈数据可以共享。
缺点:存在栈中的数据大小与生存期必须是确定的,因此缺乏灵活性。
3):每个java应用都唯一对应一个JVM实例,每个实例唯一对应一个堆。堆是一个运行时数据区。
堆中存放的是应用程序在运行中所创建的所有类实例或数组,并由应用程序的所有线程贡献。这些对象通过new,newarray,anewarray和multianewarray等指令建立。
优点:堆由垃圾回收来负责,可以动态的分配内存大小,生存期也不必实现告诉编译器,因为它是在运行时动态分配内存的,java的垃圾收集器会自动收走这些不再使用的数据。
缺点:由于要在运行时动态分配内存,存取速度较慢。
在java中分配堆内存是自动初始化的,所有对象的存储空间都是在堆中分配的,但是这个对象的引用却是在堆栈中分配的。因此建立一个对象的时候两个地方都要分配内存,在堆中分配的内存实际建立这个对象,而在堆栈中分配的内存只是一个指向这个堆对象的指针(引用)而已。