在物理内存中观察CLR托管内存及GC行为

虽然看了一些书,还网络上的一些博文,不过对CLR托管内存细节依然比较模糊。而且因为工作原因总会有很多质疑,想要亲眼看到内存里二进制数据的变化。

所以借助winhex直接查看内存以证实书上的描述或更进一步揣摩CLR托管内存的运作方式,这里写下来跟大家一起分享(由于自己这方面知识储备不太充足,下面的好多内容也是猜测,肯定有很对错误,希望了解的网友可以帮忙指正)

 

测试环境: windowsXP win10 win7 (dotnet4.0 Releases编译 ,下文截图为win7上的运行结果)

内存查看工具: winhex 7.5

 

虽然重点是监测二进制的内存,不过基本的测试代码还是要有的(测试是直接运行编译好的exe,没有使用调试模式,编译时要使用Releases,因为debug跟Releases在GC回收时对象是否可达的判断是不一样的)

下面对内存的查找部分看起来可能有点跳跃,因为是借助了反复测试得到的规律,很多过程没有赘述

 

进行之前需要先简单了解CLR对象分配(类型对象指针要知道),GC的基本过程(G0,G1,G2需要简单了解),二进制数据的存储(主要是大小端)

 

下图是测试中用到的引用对象的结构

 

 下图为测试的主要步骤,会分8步进行,每一步也都标注出来了

 

 

 

 第1监测点

 

通过TestForGC_3对象里的值类型87564023523 (hex 146338F6E3 ,windows为小端存储,所以最后搜索E3 F6 38 63 14)

前面的78 41 9B 92 为32位类型对象指针 后面接着的是同步块索引 (如果是64位程序这2个数据则都将是64位)

 

 

根据前面TestForGC_3的地址70354802,我们在内存里搜索到了唯一的一个匹配项,说明这里一定是张表,这个指针指向了TestForGC_3的地址

 

 

这个就是 NextObjPrt 了  (这个也只是推测,根据后面的操作发现新增对象末尾地址总是002BFB

48里面的数据,以及之前的反复测试前面的类型指针也是匹配的,但测试结果并不是每次这个类型指针都是这个值,并且在不同系统版本下差距非常大)

后面的操作大家可以看到它的确就是NextObjPrt ,整个内存块里存着这个地址的位置也只有这里

 


第2监测点

 

 

按照顺序我们通过内存搜索先找到了a1的地址

这里顺便解析下对象(引用类型)在内存里的存储

最前面8字节为类型对象指针及同步块索引(每个32位,如果是64位应用则每个64位)

类型对象指针不是一成不变的,就是dotnet内置的类型也不能保证,这次运行是一个值(地址),另外一个实例运行起来可能是另外一个(地址) (这里的地址全部使用偏移地址)

后面接着的3个8字节数据发布是TypeA里3个引用类型变量的地址,可以看到第2个地址就紧接在下面(因为是一起分配的)

顺便看下string类型在内存里的存储

 

根据a1里面的存储的地址02483588,轻松定位到了“testtypea”字符串

同样与其他对象一样拥有类型对象指针,同步索引块,后面有4个字节的数据长度,然后后面跟数据

这也的确说明了string千真万确引用类型,毫无争议

最后TypeA里面还有一个引用对象TypeB,是一样的就不重复说了,不过TypeB的指针只存在a1里面(即他的回收确实也只能靠根搜索)

 

 

现在我们通过a1的位置,查找内存中含有其地址的内存,居然搜索到了5块内存,而且都靠的非常近

 

 

 

 

同样的方法搜索到bytesStart在内存里的地址

同样的结构类型指针,同步索引,后面跟8字节的长度,再后面就是数据

 

 

根据地址搜索bytesStart在内存里的指针,也只有1个(这种结果在同样环境下运行每次的表现都是已有的,不过在更换运行环境后就会有明显差异),而且也紧靠着a1的指针(可以推断他们确实是在一张“表”上)

 

 

现在看下刚刚找到的NextObjPrt里面的数据是多少(02486988),下面我们看下这个地址里是什么

 

 

可以看到就指向了最后分配的bytesStart地址的后面

每个引用对象后面都有8个全0的字节(多次测试,反复分析数据都是这样)

 


监测点3 (为了验证刚刚的NextObjPrt的确是那块内存)

 

到第3步,可以直观的看到bytesThen就直接使用了刚刚NextObjPrt后面指向的内存,

 

 

 

同时也看到NextObjPrt指示下的一片内存(这个时候对A0 6D 48 02 的搜索也证明内存里只有这么一块存的是这个数据)

而且可以看到这个地址确实就是bytesThen后面的内存地址

 


第4监测点 (重复创建10分份的typeA)

 

 

这次直接使用类型对象指针搜索新创建的10份TypeA (可能会搜索出其他数据,因为内存里有其他程序及测试前几次运行残留的数据)

可以看到这些TypeA直接分配在了bytesThen的后面(测试中尽量少使用终端打印。终端打印虽然1行代码,不过clr会创建很多对象去完成打印,不方便观察)

 

 

 

现在想知道这些TypeA的指针,却发现内存里根本没有这个地址(后面9个的结果一样)

甚至连里面的TypeB的指针也搜索不到

 

其实这些TypeA从一创建即为不可达,因为后面再也没有用到它们的地方,即一开始就没有任何对象引用过他们,在引用跟踪里一直被作为垃圾

 

 

 

这个时候NextObjPrt 已经指向了02487520

 


监测点5 (出RunCreat)

 

 

 

出RunCreat()这个方法回到RunTest()里,NextObjPrt指向依然没有变化(没有新的对象创建)。

 


监测点6 (回收G0)

 

 

执行完G0回收后 ,NextObjPrt直接变为了全0 (其实后面还有跟的8个字节的数据也变为了0,这8个字节可能为G0阀值)

 

 

 这里有个疏忽,本来先要监测a1的回收,现在发现后面的代码残留上一次的测试代码错误的把a1引用了, 所以要到这一行结束a1是垃圾

 

 

 

经过G0回收后,bytesStart  bytesThen,应该移动到G1,不过看他们在内存里的位置并没有发生任何变化(内存里也只有这一份)

那10个在RunCreat创建的TypeA也似乎没有什么变化

 

关于书上的描述跟图例,似乎在GC完成后,G0向G1的代提升会移动内存,不过现在看来并没有移动内存(目前GC把85000字节的数据当作大对象,所以这里的bytesStart  也不是大对象)

 

 

那如果bytesStart  bytesThen是存活的,不能回收,那下一个NextObjPrt也一定紧接着在bytesThen后面

整个内存符合条件的也就这么一处(即使是搜索?? 6D 48 02 也只有这一块内存符合条件),虽然这块内存看起来没有什么特别的格式

 


监测点7 (下一个地址从什么地方开始分配)

 

 

可以看到bytes这个全a的数据真的是从刚刚推测的地址开始分配内存的,在RunCreat创建的TypeA也直接被覆盖了(确实被当作了垃圾)

 

 

NextObjPrt现在也正常的指向了bytes的后面

 


监测点8

 

 

 

 

数据确实在里面被改动了,而且bytesStart  bytesThen也的确处于G1


监测点9

 这次回收除了a1 其他的bytesStart  bytesThen bytes ,应该都会被回收

 

 

之前放着bytesStart  bytesThen bytes 指针的内存 数据已经被覆盖了,现在他们都被移动到另外一块内存

而a1 现在应该由g1提升到了g2

 

 

之前存放a1指针的地址也全部被覆盖了,在内存里搜索到4块新内存,其中一块还与前面的bytesStart  bytesThen 新指针放在一起

 

 

虽然现在NextObjPrt 现在不为0 ,但也明显被重置了 (因为打印的缘故,GC后马上创建了新的对象)

也很明显,并没有覆盖前面的内存,而是直接指向了后面的内存

 

 

现在来看刚刚被认为是标记GC后下一次分配内存的地址的的内存块,现在的地址02488A88,这个地址也十分合理,正好在两次NextObjPrt 的中间

标识这个地址的确是标记GC后 新NextObjPrt的初始值

 


监测结束

跳出RunTest,马上就执行了一次完全的GC

 

上面写的比较杂乱,虽然很对东西还是没有弄明白也没有发现什么规律,不过至少可以得到下面的一些结果

1:证明了NextObjPrt 的存在,也了解他的基本行为(其结构后面数据可能还包含G0阈值等其他数据)

2:GC回收使用的标记方法的确是根搜索

3:被回收的内存不会被擦除,只是通过移动NextObjPrt标记下一个内存能被分配的位置

4:对象从G0移动到G1,内存本身不会移动(可能记录对象的指针的表会有相应更新)

5:不是每次回收都会压缩内存,大部分时间都维持原有结构

6:对象在内存中的存储细节

 

最后上面写了那么多,其实不单单就是为了看CLR物理内存,同样也是表达一种方法,用同样的方法也可以查看包括jvm在内的几乎所有进程的物理内存,同时winhex不仅可以查看,还拥有在运行时直接修改物理内存的能力。

原文地址:http://www.cnblogs.com/lulianqi/archive/2017/02/27/6471393.html


.NET社区新闻,深度好文,微信中搜索dotNET跨平台或扫描二维码关注

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/326594.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2017蓝桥杯省赛---java---B---1(购物单)

题目描述 (购物单) 思路分析 cmd 打开电脑上的计算器算(算出来的结果是00结尾,作为检测) 答案 5200

DataProtection设置问题引起不同ASP.NET Core站点无法共享用户验证Cookie

这是这两天ASP.NET Core迁移中遇到的一个问题。2个ASP.NET Core站点(对应于2个不同的ASP.NET Core Web应用程序),2个站点都可以登录,但在其中任1个站点登录后,在当前站点处于登录状态,访问另外1个站点却处于…

mybatis+spring报错PropertyAccessException 1

男生关注会更帅,女生关注会更美!mybatisspring报错PropertyAccessException 1: org.springframework.beans.MethodInvocationExceptionorg.springframework.beans.factory.BeanCreationException: Error creating bean with name ‘dataSource’ defined…

字符串暴力匹配算法+思路分析

思路分析 代码实现 package com.atguigu.kmp;/*** 创建人 wdl* 创建时间 2021/4/4* 描述*/ public class ViolenceMatch {public static void main(String[] args) {//测试暴力匹配算法String str1 "硅硅谷 尚硅谷你尚硅 尚硅谷你尚硅谷你尚硅你好";String str2&quo…

springmvc中报错Request processing failed;

今天在整个ssm的时候出现了个低级错误,找了好久才找出来,在发现真理的那一刻,我都有死的冲动了。 报错如下: HTTP Status 500 - Request processing failed; nested exception is java.lang.IllegalStateException: Optional int …

在.NET Core 上运行的 WordPress

在.NET Core 上运行的 WordPress,无需安装PHP既可跨平台运行WordPress。 在Peachpie中实现PHP所需的功能数月后,现在终于可以运行一个真实的应用程序:WordPress。 本文是基于Peachpie https://github.com/iolevel/peachpie Peachpie是一个基于Microsof…

求集合中的公共元素

package com.atguigu.TEST;import javax.swing.plaf.basic.BasicScrollPaneUI; import java.util.HashSet;/*** 创建人 wdl* 创建时间 2021/4/4* 描述*/ public class Test {public static void main(String[] args) {HashSet<String> hashSet1 new HashSet<>();H…

mybatis使用全注解的方式案例(包含一对多关系映射)

前面我写过ssh&#xff1a;ssh(SpringSpring mvchibernate)简单增删改查案例 和ssm&#xff1a;ssm(SpringSpring mvcmybatis)的案例&#xff0c;需要了解的可以去看看&#xff0c;今天我写了一下ssm(springspringmvcmybatis)全注解的方式又重新写了一遍两表增删改查的案例&…

Visual Studio 2017全面上市

自从1997年第一版发布的20年以来&#xff0c;微软Visual Studio开发工具一向以易学易用、功能齐全而闻名&#xff0c;帮助开发者以简驭繁&#xff0c;即使面对越来越快速的交付压力&#xff0c;也能大幅提高生产力&#xff0c;好整以暇。对于Visual Studio的使用者而言&#xf…

Visual Studio 2017发布会:黄金时代的家族聚会

美国时间三月七日&#xff08;北京2017年3月8日&#xff09;&#xff0c;微软正式发布了Visual Studio 2017&#xff0c;自己旗舰开发工具的最新版本。同日发布的主要产品还有 .NET Core Tooling 1.0.NET Core 微服务实例Visual Studio for Mac Preview 4Visual Studio Mobile …

java开发可以转什么软件有哪些_转行开发软件Java编程必须会什么

原标题&#xff1a;转行开发软件Java编程必须会什么要想开发软&#xff0c;Java编程必须会什么&#xff1f;最起码的就是逻辑思维要好&#xff0c;只要不是特别差就没有什么问题。数学是相对比较能够体现出一个人的逻辑思维如何。先想想自己以前上学的时候&#xff0c;数学成绩…

2017蓝桥杯省赛---java---B---2(纸牌三角形)

题目描述 纸牌三角形 思路分析 全排列特殊去重 ans/6 代码实现 package com.atguigu.TEST;class Main{public static int[] a{1,2,3,4,5,6,7,8,9};public static int ans;public static void f(int k){if(k9){int x1 a[0] a[1] a[2] a[3];int x2 a[3] a[4] a[5] …

微软开源基于云的生理学研究工具

Bio Model Analyzer是一款微软基于云的生理学研究工具&#xff0c;可以用于对化细胞交互和通信进行建模&#xff0c;现已经在GitHub上开源&#xff0c;在MIT许可之下。 研究人员使用Bio Model Analyzer (BMA) 去创建计算机模型&#xff0c;该模型可以比较健康和不健康细胞内的处…

2017蓝桥杯省赛---java---B---3(承压计算)

题目描述 7 5 8 7 8 8 9 2 7 2 8 1 4 9 1 8 1 8 8 4 1 7 9 6 1 4 5 4 5 6 5 5 6 9 5 6 5 5 4 7 9 3 5 5 1 7 5 7 9 7 4 7 3 3 1 4 6 4 5 5 8 8 3 2 4 3 1 1 3 3 1 6 6 5 5 4 4 2 9 9 9 2 1 9 1 9 2 9 5 7 9 4 3 3 7 7 9 3 6 1 3 8 8 3 7 3 6 8 1 5 3 9 5 8 3 8 1 8 3 3 8 3 2 3…

[C#7] 1.Tuples(元组)

1. 老版本代码 class Program { static void Main(string[] args) { var fullName GetFullName(); Console.WriteLine(fullName.Item1);// Item1,2,3不能忍&#xff0c;&#xff0c;, Console.WriteLine(fullName.Item2); Console.WriteLine(fullName.Item3); } static Tuple&…

mysql 行转列分级输出_MySQL如何实现行转列分级输出?_MySQL

概述好久没写SQL语句&#xff0c;今天看到问答中的一个问题&#xff0c;拿来研究一下。问题链接&#xff1a;关于Mysql 的分级输出问题情景简介学校里面记录成绩&#xff0c;每个人的选课不一样,而且以后会添加课程&#xff0c;所以不需要把所有课程当作列。数据表里面数据如下…

Visual Studio 2017正式版离线安装及介绍

Visual Studio 2017 RTM正式版离线安装及介绍。 首先至官网下载&#xff1a;https://www.visualstudio.com/zh-hans/downloads/ VS 2017 正式版介绍&#xff1a; https://www.visualstudio.com/zh-hans/vs/whatsnew/ VS 2017 离线模式只离线.NET Core部分&#xff1a; Visual S…

Linux下查找命令

转载自 Linux下查找命令 一.Linux查找文件的相关命令 常 用 命 令 简要中文说明 程序所在目录 more 分页显示一个文件或任何输出结果 /bin less 分页显示一个文件并且可以回头 /usr/bin whereis 寻找文件工具 /usr/bin find 寻找文件工具 /usr/bin locate 寻…

Visual Studio 2017 新功能(上)

开发&#xff1a;快速导航、编写并修复代码 新的安装体验 - 降低了最小内存需求量以实现更快、更定制化的安装&#xff0c;并且支持脱机安装。 Visual Studio IDE - 大幅改进了 Visual Studio 2017&#xff0c;包括减少启动和解决方案加载时间、改进登录和标识、改进代码导航以…

2018蓝桥杯省赛---java---B---1(第几天)

题目描述 思路分析 31 29 31 30 4 125 答案 125