我们需要的第一件事是整理或映射一般情况下发生的事情:
您执行您的 exe 文件 -> 文件要求 .NET CLR -> CLR 进程 - 托管您的执行。
所以简而言之,我会画得更短:
这是 4.0 之前发生的事情:
执行 File1.exe -> CLR Process -> hosts (.net File1.exe) => 这里我假设 file1.exe 是 .net1
执行 File2.exe -> CLR Process2 -> hosts (.net File2.exe) => 这里我假设 file2.exe 是 .net2
执行 File3.exe -> CLR Process3 -> hosts (.net File3.exe) =>这里我假设 file3.exe 是 .net3
在上面的例子中,我假设 .net 3 安装在机器上,这就是为什么 .net3 CLR 是进程 - 确实 - 它被加载了 3 次!但是,由于 DLL 是相同的 DLL,因此 Windows 可能会共享它,就好像它只加载了一次一样。但在内存中 - 使用了 3 个不同的指令指针,每个进程都有自己独立的堆。
这就是 4.0 和 4.5 发生的情况:
执行 File4.exe -> CLR Process45 -> hosts (.net File4.exe) =>这里我假设 file4.exe 是 .net4
执行 File45.exe -> CLR Process45 -> 还有hosts (.net File45) =>这里我假设 file45.exe 是 .net4.5
在上面的示例中,我假设机器上安装了 .net 45,因此 .net CLR4 是仅加载一次的进程(而不是两次!正如前面示例逻辑所预期的那样)
您可以在我在答案末尾提供的链接中阅读更多内容,以了解哪些版本可以“坐在一起”——并非所有版本都可以与所有版本并排。
我的回答的第二部分与您确切提出的问题更相关:
任何进程都有一个单一的堆 - 因为它是硬件的工作方式,所以无法更改。
(不管CLR在这个意义上只是另一个进程可以做什么)
但是为了能够为每个托管的exe提供一个堆,他们发明了一个名为“blob-heap”的概念,它被放置在CLR进程的堆中. 可以一次管理如此多的 blob 堆。
CLR 中的每个托管应用程序都有自己的 GC,它们是隔离的,彼此不了解。
据我了解,.NET4 中只使用了一个 CLR,它能够管理许多主机项或应用程序。这意味着许多应用程序可能会相互减慢速度,但即使使用“Multi-CLR”方法也是如此。更严重的问题是,如果 CLR 本身停止运行......所有托管应用程序都将停止运行它。我不知道在架构中如何或是否解决了这种潜在问题。
我从所有这些来源中阅读以汇编这个答案:
Common Language Runtime (CLR)
ECMA C# and Common Language Infrastructure Standards
Common Language Infrastructure (CLI) Partitions I to VI (6th edition)
In-Process Side-by-Side
Loading multiple CLR Runtimes (InProc SxS) – 示例代码