栈、堆内存到底是如何申请的,方法是如何入栈出栈的——内存结构理解学习
2017-01-12 15:10
288 查看
Lee出品,转载请注明出处http://blog.csdn.net/hnulwt/article/details/42934365
对于软件开发者而言,理解和熟悉计算机内存知识是很基础的。今天我就来翻翻旧账,回顾看看有哪些点遗漏了,在此共同学习。
提起内存,我们常常想到三个区域:
1,静态区,静态变量 static variables / constant ,常量,静态变量就存储在静态区域,这个区域比较简单,只需要知道怎么通过地址访问他就行了。
2,堆 动态变量 关键字new 。通过new 创建的对象,会存储在堆中。
Java中当new的对象不再被引用时候,垃圾回收器就会在适当的时候回收这部分内存。在C/C++中则需要手动释放。
3,栈,,也叫堆栈(这里要注意堆栈 和 栈 是不同的)局部变量 创建的值会存储在栈中。
我们看看计算机中静态区域、堆、栈在内存中图示:
我们试着来分析一段Java代码,来看看内存究竟是如何分配的。
先看看代码,代码很简单:
[java]
view plain
copy
class Point {
private int px;
private int py;
public Point(int x, int y) {
px = x;
py = y;
}
public void move(int dx, int dy) {
px += dx;
py += dy;
}
}
public class Test {
public void test() {
Point p1 = new Point(2, 3);
Point p2 = new Point(4, 5);
p1.move(10, 11);
}
}
看清楚上面方法后,接着分析调用test方法:
程序在运行到test方法第一行时,由于有new,在堆上,我们申请了内存,在1004位置上存了2,在1008位置上存了3,overhead部分是一些额外的内存开销,在此我们不关注。在栈上,我们FFFC位置上存储了刚才在堆上创建的对象的首地址。同理,test第二句也是这样执行。如下图所以,该图就是test方法前俩句执行完毕后,在堆、栈的样子。
接着,调用了p1.move(10, 11),从上图看,这时我们要调用他,首先在栈上创建的是对象指位器,也叫this指位器。这个this是用来做什么的呢?this用来指示对象本身,他是如何指向本身的,下图中可以明了的看出,this右边就是指向当前对象的地址,也就是下图中的红色区域。
接着,我们可以得到dx,dy,注意栈是向上分配的,也就有了下图中的表示,他们的值分别是10,11。这时候我们才真正进行move动作,也就是加数值操作,先move方法第一行,我们把dx的值加到px上。第二行同理。
该方法执行完毕了,我们知道,当栈上的变量停止访问,也就是他不在用了,操作系统就会对这段内存进行回收。即出栈操作,执行完出栈操作后,下图中黄色的部分也就消失了。假如接着还有其他方法执行,这时候就在FFF8地址之前,也就上面继续进行。
对于软件开发者而言,理解和熟悉计算机内存知识是很基础的。今天我就来翻翻旧账,回顾看看有哪些点遗漏了,在此共同学习。
提起内存,我们常常想到三个区域:
1,静态区,静态变量 static variables / constant ,常量,静态变量就存储在静态区域,这个区域比较简单,只需要知道怎么通过地址访问他就行了。
2,堆 动态变量 关键字new 。通过new 创建的对象,会存储在堆中。
Java中当new的对象不再被引用时候,垃圾回收器就会在适当的时候回收这部分内存。在C/C++中则需要手动释放。
3,栈,,也叫堆栈(这里要注意堆栈 和 栈 是不同的)局部变量 创建的值会存储在栈中。
我们看看计算机中静态区域、堆、栈在内存中图示:
我们试着来分析一段Java代码,来看看内存究竟是如何分配的。
先看看代码,代码很简单:
[java]
view plain
copy
class Point {
private int px;
private int py;
public Point(int x, int y) {
px = x;
py = y;
}
public void move(int dx, int dy) {
px += dx;
py += dy;
}
}
public class Test {
public void test() {
Point p1 = new Point(2, 3);
Point p2 = new Point(4, 5);
p1.move(10, 11);
}
}
看清楚上面方法后,接着分析调用test方法:
程序在运行到test方法第一行时,由于有new,在堆上,我们申请了内存,在1004位置上存了2,在1008位置上存了3,overhead部分是一些额外的内存开销,在此我们不关注。在栈上,我们FFFC位置上存储了刚才在堆上创建的对象的首地址。同理,test第二句也是这样执行。如下图所以,该图就是test方法前俩句执行完毕后,在堆、栈的样子。
接着,调用了p1.move(10, 11),从上图看,这时我们要调用他,首先在栈上创建的是对象指位器,也叫this指位器。这个this是用来做什么的呢?this用来指示对象本身,他是如何指向本身的,下图中可以明了的看出,this右边就是指向当前对象的地址,也就是下图中的红色区域。
接着,我们可以得到dx,dy,注意栈是向上分配的,也就有了下图中的表示,他们的值分别是10,11。这时候我们才真正进行move动作,也就是加数值操作,先move方法第一行,我们把dx的值加到px上。第二行同理。
该方法执行完毕了,我们知道,当栈上的变量停止访问,也就是他不在用了,操作系统就会对这段内存进行回收。即出栈操作,执行完出栈操作后,下图中黄色的部分也就消失了。假如接着还有其他方法执行,这时候就在FFF8地址之前,也就上面继续进行。
相关文章推荐
- Curl命令使用方法
- php、javascript、python、ruby语言对比
- 使用textswitcher进行切换动画
- 迁移学习
- 渠道与终端的含义
- php重定向http请求
- Jenkins忘记密码的修复方法(Windows/Linux)
- Spring Tool Suite 配置和使用
- 6 Django系列之关于models的sql语句日常用法总结
- dategrid对于datetime的格式化
- android 学习资料(干货汇集)
- IO模型及select、poll、epoll和kqueue的区别
- [Leetcode] 230. Kth Smallest Element in a BST
- 解决php It is not safe to rely on the system's timezone settings. You are *required* to use the date.
- 如何处理解析Json中的key为中文或数字等变态数据
- spring配置文件详解
- git 删除默认分支
- Jquery 在ios上事件委托失效?
- iframe跨域自适应高度
- mysql:使用mysqldmp命令备份数据库