Java内存中的堆和栈

Java内存中的堆和栈

堆(Heap-线程共享)

堆是由Java程序在运行时进行创建的一块内存区域,是被线程共享的一块内存区域。我们创建的对象和数组都保存在 Java的堆内存中,在堆内存中创建的任何对象都具有全局访问权限,可以从应用程序的任何位置进行引用
与此同时,垃圾收集也在堆内存上进行,以释放没有任何引用的对象所占用的内存。由于现代Java虚拟机 采用分代收集算法,因此 Java 堆从 GC 的角度还可以细分为: 新生代(Eden 区、From Survivor 区和 To Survivor 区)和老年代。

栈(Stack-线程私有)

执行一个线程时,会为其开辟一块单独的栈内存,栈内存按照先进先出的顺序来进行管理。每当调用一个方法时,都会在栈内存中为其开辟一块单独的区域,用于保存该方法中的变量值以及对其他对象的引用。当该方法执行结束后,栈内存将会回收为该方法分配的内存区域,当有新的方法需要执行的时候,则可将该区域重新分配给新的方法。同时,与堆内存相比,栈内存的内存空间通常非常小。

比较

  1. 堆内存中的数据是全局共享的,而栈内存中的数据仅能由其对应的线程所使用
  2. 堆内存中存储的是对象,栈内存中存储的是基本数据类型(int,double,char等),对对象的引用。需要注意的是String的本质是一个对象
  3. 栈内存按照先进先出的顺序来进行管理
  4. 栈内存的生命周期是比较短暂的,当其对应的线程执行完毕,该栈内存所占据的空间便会被回收以给其它线程使用。而堆内存的生命周期是从应用程序执行开始一直到结束。
  5. 在Java程序执行的过程中,若遇到栈内存已满时,将引发java.lang.StackOverFlowError。而如果堆内存已满,则将引发java.lang.OutOfMemoryError: 与堆内存相比,堆内存的大小要小得多。

需要注意的是,我们在Java中声明的static类型的全局变量虽然也是全局共享,却不是放在堆内存中的,而是放在方法区中的。同样,方法区也是全局共享的,用于存储被 JVM 加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。
可以参考如下的Java内存模型图。
在这里插入图片描述

结合具体代码看堆和栈的作用

代码

public class Memory {
	public static void main(String[] args) { 
		int i=1; 
		Object obj = new Object(); 
		Memory mem = new Memory();
		mem.foo(obj); 
	}
	
	private void foo(Object param) { 
		String str = param.toString();
		System.out.println(str);
	} 
}

分析

  1. main方法是程序执行的入口,当执行main方法的时候,Java会创建一个供main线程所使用的栈内存,并为main方法单独开辟一块区域用于存放main方法中的局部变量。
  2. 执行int i =1的时候,会将常量保存到main方法的栈内存中。而Object obj = new Object()Memory mem = new Memory()则是创建了两个对象。对象保存到堆内存中,栈内存保存的只是对其的一个引用。
  3. 执行到mem.foo(obj)的时候,java程序知道这里将会执行一个新的方法,于是会在main线程的栈内存中再开辟一块空间,用于单独存放foo方法的局部变量,然后便进入foo方法。这里需要注意的是Java中的值传递。如果传入foo方法的是一个常量值,则会在foo方法中将其单独拷贝一份出来,比如:若往foo方法传了变量i,但是变量i在main方法和foo方法之间是不共享的(除了全局变量),因此在foo方法中也会单独拷贝一份i变量出来。而传递的若是一个对象,则会产生一个新的引用指向堆内存中的对象。于是foo方法的栈内存中会产生一个新的引用指向Object对象。
  4. String str = param.toString()会将Object对象param转为为一个字符串(字符串对象),然后将其放入字符串常量池中,字符串常量池同样也是在堆内存中,因为其本质还是对象。
  5. 当foo方法执行完毕以后就会将在栈内存中分配给foo方法的内存空间进行回收。
  6. 当main方法也执行完毕以后,程序到此结束,分配给main方法的的栈内存会被释放,给main线程的栈内存也会被释放,所有被占用的内存也都会被释放。

在这里插入图片描述
foo方法执行完毕以后则会将其从栈内存中出栈,为其分配的内存区域也随之被回收。当该线程执行完毕以后,该线程对应的栈内存则会被释放。
在这里插入图片描述

参考链接
Java Heap Space vs Stack – Memory Allocation in Java

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值