一、JVM在运行时会将数据区划分到不同的内存区域去管理,在JVM进程运行时,会将数据分为以下区域:
1、线程私有的区域:程序计数器、本地方法栈和虚拟机栈
2、线程共有的区域:堆和方法区
A、程序计数器:是标识当前线程执行字节码的行号计数器,是唯一不会有OUTOFMEMORY错误的区域
B、虚拟机栈:是线程私有内存,描述了Java方法执行的内存模型,在线程执行过程中,每一个方法对应一个栈帧,方法调用对应一个栈帧的入栈,方法结束对应栈帧的出栈;
C、本地方法栈:与虚拟机栈的作用类似。不同之处在于,虚拟机栈是为虚拟机执行JAVA方法,本地方法栈为虚拟机执行NATIVE方法
D、堆:是被所有线程共享的内存区域,可以存放JAVA对象及数组,在虚拟机启动时就创建。
E、方法区:也是被所有线程访问的内存区域,主要存储类信息、常量、静态变量和程序被编译后的字节码。
二、JVM运行时数据区之堆和栈的区别
JVM运行时数据区划分为堆和栈,这种设计是十分优雅的;栈是解决数据运行逻辑的问题,而堆是解决数据存储的问题;栈是数据运行时单位,堆是数据存储单位;
为什么要设置堆栈分离呢?
1、这种设计体现了分而治之的思想,堆代表了存储,栈代表了逻辑,这样逻辑更为清晰。
2、这种设计,使得堆中的数据可以被所有栈共享,一方面提供了共享内存这种有效的数据交互方式,另一方面使得堆数据和缓存可以被所有栈共享,节省空间。
3、这种设计,由于栈本身的特点,只能向上增长,限制了存储能力;而堆的对象可以动态增长,栈只需记录堆中的地址。
4、这种设计,体现了面向对象的思想;面向对象的思想,更接近自然思考的方式;而对象的属性就是数据,存放在堆中,对象的行为就是处理逻辑,放在栈中。
堆和栈中分别存放的内容
堆中存放的是对象、数组和基本数据类型的包装类,栈中存放的是基本数据类型和对象的引用;堆中的对象大小不固定,可以动态扩展,而栈中只存放了对象的引用,这个引用的大小是4Byte; 基本数据类型也是放在栈中存储的,由于基本数据类型的大小是固定的,占用空间不大,放在栈中不是问题;
堆和栈是程序运行最根本的东西,程序有了堆栈才可以运行;而堆栈分离,使得垃圾回收成为可能。
三、堆中存储对象的大小
当一个对象在堆中被创建的时候,如果只是空对象,会占有8byte的空间。
Object o = new Object();
当以上这个代码被执行后,就创建了一个新的对象,它占用的空间大小为4B+8B=12B;其中的8B是在堆中占用的空间,4B是栈中对象引用占用的空间大小。
由于非基本类型的对象都默认继承自Object,因此任何非基本类型的对象被创建后,其大小都是8B。
所以当以下程序代码执行后,可以计算这个对象占用空间的大小:
Class Test{
int number;
boolean flag;
Object o;
}
空对象大小 8B,int大小 4B,boolean 大小 1B,空Object引用大小4B
这个对象被创建的大小为 17B,但是JAVA在对对象分配时是按照8的倍数来分的,因此它占用的大小为24B。
基本数据类型的包装类应该被当作对象来看待,存放到堆中;包装类型的大小至少是12byte(声明一个空Object至少需要的空间),而且12byte没有包含任何有效信息,同时,因为Java对象大小是8的整数倍,因此一个基本类型包装类的大小至少是16byte。
原文:https://www.cnblogs.com/aqingsir/p/14621540.html