今天来介绍java中的堆和栈的应用
jvm运行时的数据区
jvm运行时划分了以下五个区域
JVM栈
JVM栈(stack)服务的就是不带native的方法所执行的内存空间,局部变量会保存在栈帧里面。 java栈有以下几个特性
- 每当java程序执行一个方法,都会在线上分配一块只属于这个方法内存区域,称为的栈帧。
- 每当java程序执行一个方法,都会将一个存储该方法信息的栈帧压入栈中,称为方法进栈
- 方法进栈同时局部变量开辟内存空间存储值,局部变量生效
- 当方法执行完毕之后,该方法的栈帧随之销毁,称之为出栈
- 方法栈帧被销毁的同时,局部变量也被销毁,局部变量失效
只有处于栈顶时,对应的栈才会生效,表示正在执行的栈,称为当前栈。
栈帧里面存储的内容有这么几大类
- 局部变量表
- 操作栈
- 动态连接
- 返回地址
例如如下代码:
public class TestPlayground {
public static void main(java.lang.String[] args){
a1();
}
public static void a1(){
System.out.println("111");
a2();
}
public static void a2(){
System.out.println("2222");
}
}
栈应该是这样运作的
堆
堆(heap)是JVM内存中最大的一块,所有引用数据类型,new出来的东西(对象或者实例)都放在堆上。
所以new关键字的语义就是在堆上开辟一片空间给相应的对象。这片空间就是内存地址,这个内存地址是留给外界访问的。
定义引用数据类型时的栈和堆
在引用数据类型创建时,即在堆内存了内容,也在栈里面存了内容 比如:
int[] arr=new int[3];
可以把这段代码看成两部分,右边 new int[3] 是数组的创建,左边 int[] arr 是创建了一个引用数据类型的局部变量,所以:
new int[3]:创建在堆内
int[] arr: 创建在栈内,栈内存的是堆内存的地址
即:
栈和堆的生命周期
栈:栈帧出栈了,生命周期就结束了。
堆:堆上的对象使用完毕后,随着方法的出栈,对象的引用就会被销毁。这个时候对象就没有引用指向它,而是"孤零零"的单独存在于堆上,这种对象意味着我们就无法再次使用它了,这种对象没有意义了。在Java中,我们把这种对象称之为垃圾或者垃圾对象,它们会等待垃圾回收器进行内存回收。
垃圾回收机制(Garbage Collection简称GC)
- 堆上的对象变成
垃圾后,并不是立刻就会被回收,而是需要GC通过一系列的算法来决定它是否被回收。- Java的GC机制是全自动的,程序员几乎无法干涉和主动回收
垃圾。这一方面为Java程序员的开发节省了大量的精力(无需花费大量精力来管理堆内存),相比于C++的全手动回收垃圾对象,Java在GC机制上的创新是Java能够如此流行的重要原因之一。但另一方面,一旦GC这种机制出现问题,对Java而言将会是非常难以解决的问题。malloc() free()- 垃圾回收是Java和C++之间的一道围墙,墙外的人想进来,墙内的人却想出去。