对象创建内存(主要对栈和堆的理解)
JAVA在程序运行时,在内存中划分5片空间进行数据的存储。分别是:1:栈。2:堆。3:方法区
4:寄存器 5:本地方法栈
目录
1:栈。
2:堆。
3:方法区
4:寄存器
5:本地方法栈
6:栈和堆实例分析
1. 栈。
定义
Java栈的区域很小 , 大概2m左右 , 特点是存取的速度特别快
栈存储的特点是, 先进后出
存储速度快的原因:
栈内存, 通过 '栈指针' 来创建空间与释放空间 !
指针向下移动, 会分配新的内存, 向上移动, 会释放这些内存 !
这种方式速度特别快 , 仅次于PC寄存器 !
但是这种移动的方式, 必须要明确移动的大小与范围 ,
明确大小与范围是为了方便指针的移动 , 这是一个对于数据存储的限制, 存储的数据大小是固定的 , 影响了程序 的灵活性 ~
所以我们把更大部分的数据 存储到了堆内存中
总结
栈 存贮 基本数据类型,对象引用变量
栈 大小范围固定
栈内存特点,数数据一执行完毕,变量会立即释放,节约内存空间, 速度快。
栈内存中的数据,没有默认初始化值,需要手动设置。
1. 堆。
定义
Java 中 堆 是 一种通用的内存池,用于存放所有Java 对象。
new关键字, 是指告诉JVM , 需要明确的去创建一个新的对象 , 去开辟一块新的堆内存空间,
与栈不同 ,优点在于我们创建对象时 , 不必关注堆内存中需要开辟多少存储空间 , 也不需要关注内存占用 时长 !
缺点 开辟内存及清理相对栈要更多时间
总结
堆内存用来存放new创建的对象和数组。
堆 没有固定大小范围限制 用法灵活但速度较慢
堆内存中所有的实体都有内存地址值。
堆内存中的实体是用来封装数据的,这些数据都有默认初始化值。
堆内存中的实体不再被指向时,JVM启动垃圾回收机制,自动清除
3. 方法区
定义
存放
类信息,静态变量,常量,成员方法
方法区中包含了一个特殊的区域 ( 常量池 )(存储的是使用static修饰的成员)
4. PC寄存器
定义
PC寄存器保存的是 当前正在执行的 JVM指令的 地址 !
在Java程序中, 每个线程启动时, 都会创建一个PC寄存器 !
5. PC寄存器
定义
保存本地 native 方法的地址
6. 栈和堆实例分析
例1
基本数据类型赋值与方法调用(基本数据类型的包装类型与基本类型一样)
public static void main(String[] args) {
int a=0;
test(a);
System.out.println(a);
}
static void test( int a){
a=1;
System.out.println(a);
}
输出
1
0
分析
第1步——main()方法是程序入口,JVM先执行,在栈内存中开辟一个空间,存放int类型变量a,同时附值0。
第2步——JVM执行test(a)方法,在栈内存中又开辟一个新的空间, 存放int类型变量a,同时附值1。
此时main空间与test空间并存,互不影响。
第3步——test()执行完毕,变量a立即释放,空间消失。但是main()函数空间仍存在,main中的变量a仍然存在,不受影响。
例2
public static void main(String[] args) {
MyInt a=new MyInt();
a.setValue(0);
test(a);
System.out.println(a.getValue());
}
static void test( MyInt a){
a.setValue(1);
System.out.println(a.getValue());
}
static class MyInt{
public int value;
public int getValue() {
return value;
}
public void setValue(int value) {
this.value = value;
}
}
输出
1
1
分析
第1步——main()方法是程序入口,JVM先执行,
在栈内存中开辟一个空间,存放a变量(x变量是局部变量),在堆内存中开辟一个空间,存放new MyInt()对象 存放堆内存地址 假如为:0x01 并将这个地址赋值给变量 a ,这时变量a 就指向了new MyInt()对象 的堆内存空间 。
第2步——main() 中执行 a.setValue(0)
即在 堆内存的对象空间中将0 赋值给 value这个属性。
第3步——JVM执行test(a)方法,在栈内存中又开辟一个新的空间, 存放变量a,同时附值 0x01 也指向。
第4步——test(a)方法 中执行 a.setValue(1)
即在0x88这个内存地址的 堆内存中将1 赋值给 value这个属性。
第5步——test()执行完毕,变量a立即释放,栈空间消失,但堆内存仍然存在,main中的变量a仍然指向0x01这个堆内存的内存地址。
main()和方法test() 同时对 堆内存中的值操作相互影响
例2
public static void main(String[] args) {
int [] a= new int [1];
a[0]=0;
test2(a);
System.out.println(a[0]);
}
static void test2( int [] a){
a[0]=1;
System.out.println(a[0]);
}
输出
1
1
分析
同例2 数组也是堆内存会相互影响