举例分析Java中的堆内存与栈内存

在运行Java程序时,有可能会遇到程序内存溢出而报错的情况,如下

package 面向对象设计模式;
import 面向对象设计模式.Person;
public class Test {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Person p = new Person();
		p.eat();
	}

}
package 面向对象设计模式;

public class Person {
	public String name;
	public int age;
	public Person() {
		System.out.println("I......");
	}
	public void eat() {
		this.sleep();
		System.out.println("This is A....");
	}
	public void sleep() {
		this.eat();
		System.out.println("This is B...");
	}
}

在这里插入图片描述

这是由于栈内存溢出而导致的。

首先介绍在Java中,内存分为两种:

  • 堆内存:用于存储Java中的对象和数组,其特点是先进先出,后进后出(同时有入口和出口)。它是在运行时动态分配内存的,但也因此使得存取速度较慢。
  • 栈内存:主要用来存放方法或者局部变量等,用于执行程序用的。比如:基本类型的变量和对象的引用变量。它的特点是:先进后出,后进先出(只有一个口)。它的存取速度比堆要快,仅次于寄存器,栈数据可以共享,但也因此缺乏灵活性。

接下来分析例子中为何会使得栈内存溢出

  • Test类中的p对象存放在堆中,首先执行public Person(),然后调用Person类中的eat()方法。
  • 而Person类中的变量及方法都存储于栈中,当程序运行到eat()方法时,会在栈中创建一个void类的方法对象引用eat()方法(入栈),然后查找栈中有没有存放
{
		this.sleep();
		System.out.println("This is A....");
	}

这个方法,如果没有,则将方法存放进栈中,并令eat()指向其内容,如果已经有该方法内容,则直接令eat()指向其内容,相当于指向存放方法内容的地址。
在运行到eat()方法时由于遇到this关键字,调用了Person类中的其他方法sleep(),因此会在栈中创建一个void类的方法对象引用sleep()方法(入栈),然后查找栈中有没有存放

{
		this.eat();
		System.out.println("This is B...");
	}

这个方法,如果没有,则将方法存放进栈中,并令sleep()指向其内容,如果已经有该方法内容,则直接令sleep()指向其内容,相当于指向存放方法内容的地址。
而在运行sleep()方法时也遇到了this关键字,调用了Person类中的其他方法eat(),因此不断在栈中创建eat()和sleep()方法,且两个方法由于都无法结束,因此无法出栈,使得栈溢出,程序报错。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

阿_巴打

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值