JVM内存模型
JVM运行时数据区域
一个Java程序在虚拟机运行的过程中,会在JVM内存中创建很多变量,这些变量不是杂乱无章的摆放的,而是被JVM分区域管理的。这个区域就是JVM的运行时数据区域,这些区域各有各的用途,创建时间,销毁时间等皆有不同。内存中变量的生命周期、特点和使用方式也会随之产生差异。
- 理解JVM运行时内存是学习Java的基本,能够加深我们对Java中的很多现象的理解
JVM内存模型图
为了更好的描述JVM内存空间,Java的开发者,在《Java虚拟机规范》中指出:JVM (运行时数据区)内存共分为JVM栈,堆,方法区,程序计数器,本地方法栈五个部分。
JVM内存模型详解:
1,JVM栈(以后简称栈,stack):描述的是Java方法执行时的内存模型
程序运行时调用方法的代价是:要占用栈的内存空间,栈中主要存储着局部变量
a,每当Java程序执行一个方法,都会在栈上分配一块只属于该方法的内存区域,称之为“栈帧”
b,也就是说,每当Java程序执行一个方法,都会将一个存储该方法信息的栈帧压入栈中,称之为“方法进栈”
c,方法进栈的同时局部变量进行声明和初始化,局部变量生效
d,当方法执行完毕后,该方法的栈帧随之销毁,称之为“方法的出栈”
f,栈帧被销毁的同时,局部变量也被销毁,局部变量失效
2,堆(heap):堆是JVM内存中最大的一块,new出来的东西(称之为对象)都在堆上
使用new关键字,意思是在堆上开辟一片空间给相应的对象
这片空间是有内存地址的,这个内存地址是留给外界访问用的
3,方法区(method area):面向对象详细讲
4,本地方法栈:和JVM栈类似,区别是本地方法栈是给本地(native)方法使用的
5,程序计数器:JVM执行代码是一行一行执行字节码,程序计数器用来记录当前执行的行数
什么是引用数据类型(数组初始化的内存分配过程)
引用数据类型是Java的两个数据类型之一。引用数据类型的创建分为两部分:
1,首先是在栈上分配一片空间给引用数据类型的引用,简称“引用”
2,在堆上开辟一片空间,用于存放引用数据类型的具体信息,称之为“对象”或者“实例”
对象是引用数据类型的实质
3,栈上的引用指向了堆上对象的内存地址
4,我们只能通过引用(变量名)去间接的访问,堆上的对象。无法直接访问堆上对象
基本数据类型和引用数据类型的区别:
1,存储位置(本质区别):
a,基本数据类型不存在”引用“的概念,数据都是直接存储在栈上的栈帧里;
b,引用数据类型在栈帧中存储引用,引用存储的只是该引用类型在堆上对象的内存地址
堆上对象存储才是引用数据类型的具体信息
2,打印变量名内容:
a,基本数据类型,打印变量名就是该变量具体的数值
b,引用数据类型,打印变量名显示该引用变量堆上的内存地址
堆上变量和栈中变量的区别
-
从存储变量的类型来看:
- 堆上存储的是new出来的东西,是引用数据类型的对象
- 栈上存储的是局部变量(基本数据类型,引用类型的引用)
-
从默认值来看:
- 堆上的变量具有默认值
- 整形(byte、short、int、long)默认值为0
- 浮点类型(float、double)默认值为0.0
- 字符类型(char)默认值是**’\u0000’ 空字符**
- 布尔类型(boolean)默认值是false
- 引用数据类型默认值是null
- 栈上变量没有默认值,声明必须显式的初始化,否则无法使用
- 堆上的变量具有默认值
-
生命周期来看:
-
堆上的对象使用完毕后,就会变成“垃圾”,会等待垃圾回收器进行内存回收
- 堆上的对象变成垃圾后,并不是立刻就会被回收,而是等待垃圾回收器进行回收
- 整个垃圾回收的过程都是由Java的垃圾回收机制自动完成的,极大的节省了Java程序员的精力
- 垃圾回收是Java和C++之间的一道围墙,墙外的人想进来,墙内的人却想出去
-
栈上的局部变量的生命周期和栈帧保持一致
- 方法栈帧进栈后,局部变量就被声明分配空间了
- 方法出栈后,局部变量就被销毁了
-