仓酷云

 找回密码
 立即注册
搜索
热搜: 活动 交友 discuz
查看: 1693|回复: 11
打印 上一主题 下一主题

[学习教程] ASP.NET网页编程之[你必需晓得的.NET]第十九回:对象创立委曲(下)仓酷云

[复制链接]
若相依 该用户已被删除
跳转到指定楼层
楼主
发表于 2015-1-18 11:25:00 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
我有个同学,他是搞net网页编程的,他给我说“net网页编程不是效率低,而是速度慢。”,我不是搞net网页编程的,我实在想不透这句话的含义,难道执行速度不就是效率低吗?难道执行速度慢还成效率高了?系列文章目次索引:《你必需晓得的.NET
本文将先容以下内容:


  • 对象的创立历程
  • 内存分派剖析
  • 内存结构研讨

<br>

接上回[第十八回:对象创立委曲(上)],持续对对象创立话题的会商>>>
2.2托管堆的内存分派机制

援用范例的实例分派于托管堆上,而线程栈倒是对象性命周期入手下手的中央。对32位处置器来讲,使用程序完成历程初始化后,CLR将在历程的可用地点空间上分派一块保存的地点空间,它是历程(每一个历程可以使用4GB)中可用地点空间上的一块内存地区,但其实不对应于任何物理内存,这块地点空间便是托管堆。
托管堆又依据存储信息的分歧分别为多个地区,个中最主要的是渣滓接纳堆(GCHeap)和加载堆(LoaderHeap),GCHeap用于存储对象实例,受GC办理;LoaderHeap又分为High-FrequencyHeap、Low-FrequencyHeap和StubHeap,分歧的堆上又存储分歧的信息。LoaderHeap最主要的信息就是元数据相干的信息,也就是Type对象,每一个Type在LoaderHeap上表现为一个MethodTable(办法表),而MethodTable中则纪录了存储的元数据信息,比方基范例、静态字段、完成的接口、一切的办法等等。LoaderHeap不受GC把持,其性命周期为从创立到AppDomain卸载。
在进进实践的内存分派剖析之前,有需要对几个基础观点做以交卸,以便更好的在接上去的剖析中睁开会商。
·TypeHandle,范例句柄,指向对应实例的办法表,每一个对象创立时都包括该附加成员,而且占用4个字节的内存空间。我们晓得,每一个范例都对应于一个办法表,办法表创立于编译时,次要包括了范例的特性信息、完成的接口数量、办法表的slot数量等。
·SyncBlockIndex,用于线程同步,每一个对象创立时也包括该附加成员,它指向一块被称为SynchronizationBlock的内存块,用于办理对象同步,一样占用4个字节的内存空间。
·NextObjPtr,由托管堆保护的一个指针,用于标识下一个新建对象分派时在托管堆中所处的地位。CLR初始化时,NextObjPtr位于托管堆的基地点。
因而,我们对援用范例分派历程应当有个基础的懂得,因为本篇示例中FileStream范例的承继干系绝对庞大,在此本文完成一个绝对复杂的范例来做申明:
将上述实例的实行历程,反编译为IL言语可知:new关头字被编译为newobj指令来完成对象创立事情,进而挪用范例的机关器来完成其初始化操纵,在此我们具体的形貌其实行的详细历程:
//@2007Anytao.com
//http://www.anytao.com
publicclassUserInfo
{
privateInt32age=-1;
privatecharlevel="A";
}

publicclassUser
{
privateInt32id;
privateUserInfouser;
}

publicclassVIPUser:User
{
publicboolisVip;

publicboolIsVipUser()
{
returnisVip;
}

publicstaticvoidMain()
{
VIPUseraUser;
aUser=newVIPUser();
aUser.isVip=true;
Console.WriteLine(aUser.IsVipUser());
}
}
·起首,将声明一个援用范例变量aUser:
VIPUseraUser;
它仅是一个援用(指针),保留在线程的仓库上,占用4Byte的内存空间,将用于保留VIPUser对象的无效地点,其实行历程恰是上文形貌的在线程栈上的分派历程。此时aUser未指向任何无效的实例,因而被自行初始化为null,试图对aUser的任何操纵将抛出NullReferenceException非常。
·接着,经由过程new操纵实行对象创立:
aUser=newVIPUser();
如上文所言,该操纵对应于实行newobj指令,其实行历程又可细分为以下几步:
(a)CLR依照其承继条理举行搜刮,盘算范例及其一切父类的字段,该搜刮将一向递回到System.Object范例,并前往字节总数,以本例而言范例VIPUser必要的字节总数为15Byte,详细盘算为:VIPUser范例自己字段isVip(bool型)为1Byte;父类User范例的字段id(Int32型)为4Byte,字段user保留了指向UserInfo型的援用,因而占4Byte,而同时还要为UserInfo分派6Byte字节的内存。
实例对象所占的字节总数还要加上对象附加成员所需的字节总数,个中附加成员包含TypeHandle和SyncBlockIndex,合计8字节(在32位CPU平台下)。因而,必要在托管堆上分派的字节总数为23字节,而堆上的内存块老是依照4Byte的倍数举行分派,因而本例中将分派24字节的地点空间。
(c)CLR在以后AppDomain对应的托管堆上搜刮,找到一个未利用的20字节的一连空间,并为其分派该内存地点。现实上,GC利用了十分高效的算法来满意该哀求,NextObjPtr指针只必要向前促进20个字节,并清零原NextObjPtr指针和以后NextObjPtr指针之间的字节,然后前往原NextObjPtr指针地点便可,该地点恰是新创立对象的托管堆地点,也就是aUser援用指向的实例地点。而此时的NextObjPtr仍指向下一个新建对象的地位。注重,栈的分派是向低地点扩大,而堆的分派是向洼地址扩大。
别的,实例字段的存储是有按次的,由上到下顺次分列,父类在前子类在后,具体的剖析请拜见[第十五回:承继实质论]。
在上述操纵时,假如试图分派所需空间而发明内存不敷时,GC将启动渣滓搜集操纵往返收渣滓对象所占的内存,我们将今后对此做具体的剖析。
·最初,挪用对象机关器,举行对象初始化操纵,完成创立历程。该机关历程,又可细分为以下几个环节:
(a)机关VIPUser范例的Type对象,次要包含静态字段、办法表、完成的接口等,并将其分派在上文提到托管堆的LoaderHeap上。

(b)初始化aUser的两个附加成员:TypeHandle和SyncBlockIndex。将TypeHandle指针指向LoaderHeap上的MethodTable,CLR将依据TypeHandle来定位详细的Type;将SyncBlockIndex指针指向SynchronizationBlock的内存块,用于在多线程情况下对实例对象的同步操纵。
(c)挪用VIPUser的机关器,举行实例字段的初始化。实例初始化时,会起首向上递回实行父类初始化,直到完成System.Object范例的初始化,然后再前往实行子类的初始化,直到实行VIPUser类为止。以本例而言,初始化历程为起首实行System.Object类,再实行User类,最初才是VIPUser类。终极,newobj分派的托管堆的内存地点,被传送给VIPUser的this参数,并将其援用传给栈上声明的aUser。
上述历程,基础完成了一个援用范例创立、内存分派和初始化的全部流程,但是该历程只能看做是一个简化的形貌,实践的实行历程加倍庞大,触及到一系列细化的历程和操纵。对象创立并初始化以后,内存的结构,能够暗示为:

<br>
由上文的剖析可知,在托管堆中增添新的实例对象,只是将NextObjPtr指针增添必定的数值,再次新增的对象将分派在以后NextObjPtr指向的内存空间,因而在托管仓库中,一连分派的对象在内存中必定是一连的,这类分派机制十分高效。
2.3需要的增补

有了对象创立的基础流程观点,上面的几个成绩经常引发人人的思索,在此本文一并做以探究:
·值范例中的援用范例字段和援用范例中的值范例字段,其分派情形又是怎样?
这一思索实际上是一个成绩的两个方面:关于值范例嵌套援用范例的情形,援用范例变量作为值范例的成员变量,在仓库上保留该成员的援用,而实践的援用范例仍旧保留在GC堆上;关于援用范例嵌套值范例的情形,则该值范例字段将作为援用范例实例的一部分保留在GC堆上。在[第八回:咀嚼范例---值范例与援用范例(上)-内存有理]一文对这类嵌套布局,有较具体的剖析。关于值范例,你只需记住它老是分派在声明它的中央。

·办法保留在LoaderHeap的MethodTable中,那末办法挪用时又是怎样的历程?
如上文所言,MethodTable中包括了范例的元数据信息,类在加载时会在LoaderHeap上创立这些信息,一个范例在内存中对应一份MethodTable,个中包括了一切的办法、静态字段和完成的接口信息等。对象实例的TypeHandle在实例创立时,将指向MethodTable入手下手地位的偏移处(默许偏移12Byte),经由过程对象实例挪用某个办法时,CLR依据TypeHandle能够找到对应的MethodTable,进而能够定位到详细的办法,再经由过程JITCompiler将IL指令编译为当地CPU指令,该指令将保留在一个静态内存中,然后在该内存地点上实行该办法,同时该CPU指令被保留起来用于下一次的实行。
在MethodTable中,包括一个MethodSlotTable,称为办法槽表,该表是一个基于办法完成的线性链表,并依照以下按次分列:承继的虚办法,引进的虚办法,实例办法和静态办法。办法表在创立时,将依照承继条理向上搜刮父类,直到System.Object范例,假如子类覆写了父类办法,则将会以子类办法掩盖父类虚办法。关于办法表的创立历程,能够参考[第十五回:承继实质论]中的形貌。
·静态字段的内存分派和开释,又有何分歧?
静态字段也保留在办法表中,位于办法表的槽数组后,其性命周期为从创立到AppDomain卸载。因而一个范例不管创立几个对象,其静态字段在内存中也只要一份。静态字段只能由静态机关函数举行初始化,静态机关函数确保在范例任何对象创立前,大概在任何静态字段或办法被援用前实行,其具体的实行按次请参考相干会商。

3.结论

对象创立历程的懂得,是从底层打仗CLR运转机制的出口,也是熟悉.NET主动内存办理的关头。经由过程本文的具体叙述,关于对象的创立、内存分派、初始化历程和办法挪用等手艺城市创建一个绝对周全的了解,同时也分明的掌控了线程栈和托管堆的实行机制。
对象老是有生有灭,本文简述其生,这是个巨大的入手下手。

参考文献
(USA)JoeDuffy,Professinal.NETFramework2.0
(USA)DonBox,Essiential.NET
(MSDN)HanuKommalapatiandTomChristian,DrillInto.NETFrameworkInternalstoSeeHowtheCLRCreatesRuntimeObjects,http://msdn.microsoft.com/msdnmag/issues/05/05/JITCompiler/default.aspx

2007Anytao.com

来自:http://www.ckuyun.com/anytao/archive/2007/12/07/must_net_19.html
完全不一样的。.net其实我也说不太清,.net可以把他理解为跟J2EE相对的工具。c++主要做系统相关的开发你要学.net的话就应该学C#。(其实微软在.NET平台上也考虑了给C++留一个地位。
谁可相欹 该用户已被删除
沙发
发表于 2015-1-21 05:38:22 来自手机 | 只看该作者
目前在微软的.net战略中新推出的ASP.net借鉴了Java技术的优点,使用CSharp(C#)语言作为ASP.net的推荐语言,同时改进了以前ASP的安全性差等缺点。但是,使用ASP/ASP.net仍有一定的局限性,因为从某种角度来说它们只能在微软的WindowsNT/2000/XP+IIS的服务器平台上良好运行(虽然像ChilliSoft提供了在UNIX/Linux上运行ASP的解决方案.
精灵巫婆 该用户已被删除
板凳
发表于 2015-1-25 18:09:55 | 只看该作者
ASP.net的服务器,要求安装一个.net环境,当然我这里指的是windows系统,顺便点一下,.net只能放在windows环境里来运行。Asp.net1.1的就装Framework1.1,Asp.net2.0的就装Framework2.0。
再见西城 该用户已被删除
地板
发表于 2015-2-2 21:45:58 | 只看该作者
逐步缩小出错代码段的范围,最终确定错误代码的位置。
冷月葬花魂 该用户已被删除
5#
发表于 2015-2-6 16:01:32 | 只看该作者
网页从开始简单的hmtl到复杂的服务语言,走过了10多个年头,各种技术层出不穷,单个的主流技术也在不断翻新的版本,现在分析下各种语言的区别、优势、劣势、开发注意事项!
柔情似水 该用户已被删除
6#
发表于 2015-2-8 06:25:57 | 只看该作者
同时也感谢博客园给我们这个平台,也感谢博客园的编辑们做成专题引来这么多高人指点。
若相依 该用户已被删除
7#
 楼主| 发表于 2015-2-24 04:33:31 | 只看该作者
Servlet的形式和前面讲的CGI差不多,它是HTML代码和后台程序分开的。它们的启动原理也差不多,都是服务器接到客户端的请求后,进行应答。不同的是,CGI对每个客户请求都打开一个进程(Process)。
山那边是海 该用户已被删除
8#
发表于 2015-3-1 11:30:23 | 只看该作者
JSP/Servlet虽然在国内目前的应用并不广泛,但是其前途不可限量。
变相怪杰 该用户已被删除
9#
发表于 2015-3-6 13:56:55 | 只看该作者
如今主流的Web服务器软件主要由IIS或Apache组成。IIS支持ASP且只能运行在Windows平台下,Apache支持PHP,CGI,JSP且可运行于多种平台,虽然Apache是世界使用排名第一的Web服务器平台。
深爱那片海 该用户已被删除
10#
发表于 2015-3-13 01:09:42 | 只看该作者
CGI程序在运行的时候,首先是客户向服务器上的CGI程序发送一个请求,服务器接收到客户的请求后,就会打开一个新的Process(进程)来执行CGI程序,处理客户的请求。CGI程序最后将执行的结果(HTML页面代码)传回给客户。
再现理想 该用户已被删除
11#
发表于 2015-3-20 08:43:49 | 只看该作者
但是目前在CGI中使用的最为广泛的是Perl语言。所以,狭义上所指的CGI程序一般都是指Perl程序,一般CGI程序的后缀都是.pl或者.cgi。
小女巫 该用户已被删除
12#
发表于 2015-4-12 13:53:50 | 只看该作者
目前在微软的.net战略中新推出的ASP.net借鉴了Java技术的优点,使用CSharp(C#)语言作为ASP.net的推荐语言,同时改进了以前ASP的安全性差等缺点。但是,使用ASP/ASP.net仍有一定的局限性,因为从某种角度来说它们只能在微软的WindowsNT/2000/XP+IIS的服务器平台上良好运行(虽然像ChilliSoft提供了在UNIX/Linux上运行ASP的解决方案.
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|手机版|仓酷云 鄂ICP备14007578号-2

GMT+8, 2024-4-26 05:17

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表