从内存变化看.NET代码执行机理
2009-03-11 11:31
127 查看
首先,要深入.NET Framework就不得不清楚其运行机理,看.NET代码运行最好的地方,莫过于Framework的托管内存变化了.
托管内存不是真实的物理内存,是Framework从物理内存上申请到的内存.物理上讲,申请到的内存就像广场一样,任何代码数据都可以往上放,并没有区别哪个地方一定存放什么类型的数据.但从逻辑功能上讲,Framework托管内存可以分为两大类:代码区和数据区.在数据区中又划分为:堆(heap)和栈(stack).
(一碗八宝粥和内存相似,粥里面有银耳,绿豆,莲子什么的就像代码区和数据区一样.他们不同的作料有不同的作用,但是不固定地方,基本没有可能出现一碗底部全部是莲子,上面全部是绿豆的粥)
代码区(特别的:静态字段,函数统统在代码区,代码区的所有数据不可复制,仅存一份.)
数据区保存各种我们.NET程序运行时要用到的数据的位置.
1
int x;
2
x=5;
第一句int x执行的时候,其中int 存入代码区.并向栈中申请一段4个字节大小的空间(为什么是4?因为X的类型是INT,所以申请的内存占4个字节).,此时申请到的空间有名称为x但没有内容.同时地址为10936.
第二句x=5执行的时候,表示在栈中申请到的空间内加入5这个值.见下图.如果现在再加一句x=13;则5被覆盖成13.
下面图示(从概念上划分):
其中10936表示数据在栈中的地址,对程序实际执行没有影响.整个内存占4个字节.堆里面是空的.
1
string str;
2
str=abc;
第一句string str执行的时候,其中string存入代码区.并向栈中申请一段空间.,此时申请到的空间有名称为str但没有内容.同时地址为10933.
第二句str=abc执行时候,在堆中整出块内存(地址为35119)把abc存入,并把内存地址35119付给str在栈中的引用.注意在堆中申请的内存没有名称.
如果再加一句str=xyz的时候,那么在堆中整出块内存(地址为13145)把xyz存入,并把内存地址13145付给str在栈中的引用.那么现在操作str就等于操作xyz.
那么现在abc怎么办?CRL的垃圾自动回收会扫到abc,了解到abc的地址没有被任何变量所引用,则自动删除回收.
在数据区当中,堆和栈分享不同的地址.栈可以直接访问,具有访问速度快的特点.堆不可直接访问,但具有容量大的特点.物理上,一根2G的内存,其栈的容量往往不到5M.现在定义的string类型中,str的容量不一定,可以无限的扩大,所以不可能把string类型的数据放到栈中.而上面的int是固定大小的,所以可以放在栈中.现在要访问abc,则先要访问35119(首地址),通过35119来访问推里面的数据.
需要强调一点是,值类型并不一定只存在栈中,比如在堆里有一块内存,地址为98168,可以在堆里起个名字叫A,值为10,那么相当于变量生成在堆里面了,这样也是值类型.任何时候这样来区分:值类型就是变量和数据存储在一起的.而引用类型则变量中存储的是数据的引用地址.
值类型的数据存储有限,一般包括:整型,浮点,字节,长整,短整,双精,结构,枚举都是值类型.大小固定!
引用类型的数据可以无限扩充的,包括:字符串,数组,类等,以上不可限定大小的一般做引用类型!
那么在内存中存储的这些数据从哪里来的?比如上面的内存10933中存储的str等等是那里来的?是不是我们输入的时候取我们的输入内容放进内存的呢?不是,而是涉及到一个字符串池的东西.
托管内存不是真实的物理内存,是Framework从物理内存上申请到的内存.物理上讲,申请到的内存就像广场一样,任何代码数据都可以往上放,并没有区别哪个地方一定存放什么类型的数据.但从逻辑功能上讲,Framework托管内存可以分为两大类:代码区和数据区.在数据区中又划分为:堆(heap)和栈(stack).
(一碗八宝粥和内存相似,粥里面有银耳,绿豆,莲子什么的就像代码区和数据区一样.他们不同的作料有不同的作用,但是不固定地方,基本没有可能出现一碗底部全部是莲子,上面全部是绿豆的粥)
代码区(特别的:静态字段,函数统统在代码区,代码区的所有数据不可复制,仅存一份.)
数据区保存各种我们.NET程序运行时要用到的数据的位置.
1
int x;
2
x=5;
第一句int x执行的时候,其中int 存入代码区.并向栈中申请一段4个字节大小的空间(为什么是4?因为X的类型是INT,所以申请的内存占4个字节).,此时申请到的空间有名称为x但没有内容.同时地址为10936.
第二句x=5执行的时候,表示在栈中申请到的空间内加入5这个值.见下图.如果现在再加一句x=13;则5被覆盖成13.
下面图示(从概念上划分):
其中10936表示数据在栈中的地址,对程序实际执行没有影响.整个内存占4个字节.堆里面是空的.
1
string str;
2
str=abc;
第一句string str执行的时候,其中string存入代码区.并向栈中申请一段空间.,此时申请到的空间有名称为str但没有内容.同时地址为10933.
第二句str=abc执行时候,在堆中整出块内存(地址为35119)把abc存入,并把内存地址35119付给str在栈中的引用.注意在堆中申请的内存没有名称.
如果再加一句str=xyz的时候,那么在堆中整出块内存(地址为13145)把xyz存入,并把内存地址13145付给str在栈中的引用.那么现在操作str就等于操作xyz.
那么现在abc怎么办?CRL的垃圾自动回收会扫到abc,了解到abc的地址没有被任何变量所引用,则自动删除回收.
在数据区当中,堆和栈分享不同的地址.栈可以直接访问,具有访问速度快的特点.堆不可直接访问,但具有容量大的特点.物理上,一根2G的内存,其栈的容量往往不到5M.现在定义的string类型中,str的容量不一定,可以无限的扩大,所以不可能把string类型的数据放到栈中.而上面的int是固定大小的,所以可以放在栈中.现在要访问abc,则先要访问35119(首地址),通过35119来访问推里面的数据.
需要强调一点是,值类型并不一定只存在栈中,比如在堆里有一块内存,地址为98168,可以在堆里起个名字叫A,值为10,那么相当于变量生成在堆里面了,这样也是值类型.任何时候这样来区分:值类型就是变量和数据存储在一起的.而引用类型则变量中存储的是数据的引用地址.
值类型的数据存储有限,一般包括:整型,浮点,字节,长整,短整,双精,结构,枚举都是值类型.大小固定!
引用类型的数据可以无限扩充的,包括:字符串,数组,类等,以上不可限定大小的一般做引用类型!
那么在内存中存储的这些数据从哪里来的?比如上面的内存10933中存储的str等等是那里来的?是不是我们输入的时候取我们的输入内容放进内存的呢?不是,而是涉及到一个字符串池的东西.
相关文章推荐
- 从内存变化看.NET代码执行机理(三)
- 从内存变化看.NET代码执行机理(一)
- 从内存变化看.NET代码执行机理(四)
- 【ASP.NET】解决执行<script>代码后页面布局变化问题
- .NET性能分析最佳实践之:如何找出使用过多内存的.NET代码(基础篇)
- 对象实例化,jvm执行时内存变化,
- [ASP.NET]实现在执行完服务端代码后弹出提醒对话框
- ASP.NET(C#) 定时执行一段代码
- 动态执行 VB.NET 和 C# 代码
- 网页调试:myeclipse修改javascript代码后,执行没有变化呀
- C#ASP.NET执行BAT批处理代码
- 让服务器控件执行js与C#两种代码(asp.net)
- 禁止在.net framework中执行用户代码。启用“clr enabled” 配置选项
- .net Button的确认提示按钮执行后台代码
- vb.net用代码创建一个内存表
- 在 ASP.NET 中使用计时器执行用户代码(原创代码)
- [转载代码]VB.NET 中查询 Linq to SQL 执行时的SQL语句
- JVM学习笔记(1、 基本结构;2、Java代码编译和执行的整个过程3、内存管理和垃圾回收 4、 内存调优 )
- Asp.net取得页面执行时间的代码