提问人:grilledCheeze 提问时间:4/27/2023 最后编辑:grilledCheeze 更新时间:4/27/2023 访问量:59
CLR 反射和元数据管理 - 真相在哪里?
CLR Reflection and Metadata management - where is the truth?
问:
我一直认为,当您实际请求所需的信息时,CLR 中的反射会按需加载类型的元数据。然后它被缓存,所有后续调用都会更便宜。至少,互联网上的一些文章是这么告诉我的。
但是,最近我读到,当在 CLR 中加载程序集时,所有类型的所有元数据也应从元数据表中加载。这是有道理的。
然而,这两种说法相互矛盾,我现在非常困惑。
如果 CLR 使用程序集加载元数据,那么为什么 Reflection 需要加载任何内容?它会从缓存中获取信息,不是吗? 如果是这样 - 那么所有关于元数据加载/缓存如何成为反射性能缓慢因素的文章 - 都在撒谎?
假设我在某个方法中创建了一个类型 A 的实例,并且该类型引用了另一个类型 B。然后,我想分析类型 B,并获取有关其所有字段的信息。它是否涉及加载任何元数据?或者它已经加载和缓存了?
或者另一种情况 - 如果在 C# 中,调用了 ValueType 的默认 GetHashCode 实现,在某些情况下,它在 CLR 端使用 Reflection - 它会获取已缓存的数据吗?
请帮助我了解这一切是如何运作的,并最终睡个好觉。
答:
0赞
Charlieface
4/27/2023
#1
这取决于你所说的“元数据”。加载程序集时,将分析整个程序集,并创建基本结构来存储有关每种类型的信息,以便 JITter 知道如何执行代码。不过,代码本身还不是 JITted。
但是,反射使用许多其他结构,这些结构对于加载和执行程序集不是必需的。例如,它可以创建 和 对象,或数组。首次使用反射时,会缓存这些内容。TypeInfo
FieldInfo
CustomAttribute
评论
0赞
grilledCheeze
4/27/2023
我是否正确理解 CLR 在程序集加载期间加载元数据,然后当 System.Reflection 包装器(假设使用 C# 端)时,调用随后被封送到 CLR 端,从元数据中获取信息,将其作为 C# 类型返回(如您提到的)并在此过程中缓存?在这种情况下,我的示例,在本机端调用并需要类型信息 - 应该是免费的(或者至少比在 C# 端获取相同信息便宜很多)?FieldInfo
GetHashCode
0赞
Charlieface
4/27/2023
给予或接受,这大约是它的大小。不确定您是否需要查看代码 github.com/dotnet/runtime/blob/... 但它似乎确实使用了本机表GetHashCode
0赞
grilledCheeze
4/27/2023
谢谢你的回答!不幸的是,我还不能投票,但真的很感激:)
评论