|
1
10
http://msdn.microsoft.com/en-us/library/system.int32.maxvalue.aspx
无限循环最终将导致相同的异常(或与过度使用RAM间接相关的另一个异常),但这需要一段时间。试着增加
|
|
|
2
7
你的
在我的系统上(.NET 4.5 x64)
虚拟地址空间
. 当这个到达时,你会得到一个
|
|
|
3
5
因为
在第二个例子中,操作系统每次只需要找到1024个字节来分配,并且可以交换到硬盘驱动器。我敢肯定,如果你让它运行足够长的时间,你会在一个黑暗的地方结束:) |
|
|
4
4
这就是说,这么大的ArrayList应该会耗尽内存,但很可能您没有让代码运行足够长的时间来耗尽内存。 |
|
5
3
第二个片段也会崩溃。它只需要花费很长时间,因为它消耗的内存要慢得多。注意你的硬盘访问灯,当Windows从RAM中抽出页面腾出空间时,它会剧烈地闪烁。第一个字符串构造函数立即失败,因为堆管理器不允许分配4G字节。 |
|
|
6
2
这两个版本都会导致OOM异常,只是(在32位机器上)当你试图分配一个“单一”非常大的对象时,你会在第一个版本中立即得到它。 第二个版本将花费更长的时间,但是由于以下几个因素,要达到OOM状态将需要大量的震荡:
抖动将导致系统停止处理开销,因此需要很长时间才能达到OOM条件。大部分时间将花在GC上,并为第二个版本进行分页。 |
|
|
7
1
在第一个示例中,您尝试一次性创建2g字符串
它也不是一次全部存储在一个变量中。因此,我认为,您的一些内存使用可以持久化到磁盘上,为新数据腾出空间。 |
|
|
8
1
我不知道ArrayList在内部是如何工作的,但是您分配了多个每个2GB的对象,而据我所知,ArrayList只包含4个指针(x64上是8个?)字节,不管它们指向的对象有多大。 引用 another article : |
|
|
9
0
您的系统可能会停止运行的一个原因是.NET的代码运行得更接近金属,而且您处于一个严格的循环中,如果进程优先级允许,它应该消耗100%的CPU。如果您想防止应用程序在执行紧循环时消耗过多的CPU,您应该添加如下内容 System.Threading.Thread.Sleep(10) JVM和.NET的CLR(公共语言运行时)之间的一个主要区别是CLR不限制x64系统/应用程序上的内存大小(在32位应用程序中,由于寻址限制,操作系统将所有应用程序限制为2GB)。JIT编译器为您的处理体系结构创建本机windows代码,然后在与任何其他windows应用程序相同的范围内运行它。JVM是一个更加孤立的沙盒,它根据配置/命令行开关将应用程序限制为指定的大小。
当在x64环境中运行时,如果有足够的连续内存来分配包含所需的4GB,则不能保证单字符串创建失败内部最大值字符(.NET字符串默认为Unicode,每个字符需要2个字节)。32位应用程序总是会失败,即使设置了大地址感知标志,因为最大内存仍然是3.5GB)。 如果您有足够的可用空间,那么代码的while循环版本可能会在抛出异常之前消耗更多的内存,因为字符串可以分配到较小的片段中,但最终肯定会遇到错误(尽管如果您有足够的资源,则可能会由于ArrayList超出数组中元素的最大数目,而不是不能为一个小字符串分配新的空间)。Kent Murra关于字符串内接也是正确的;您要么需要随机化字符串的长度或字符内容以避免内联,否则您只需创建指向同一字符串的指针。stevetownsend关于增加字符串长度的建议也会使找到足够大的连续内存块变得更加困难,这将使异常更快地发生。 编辑:
Garbage Collection: Automatic Memory Management in the Microsoft .NET Framework Garbage Collection Part 2: Automatic Memory Management in the Microsoft .NET Framework 以下是来自.NET垃圾收集开发人员的博客,以获取有关.NET内存管理更新版本的信息: So, whatâs new in the CLR 4.0 GC? CLR 4.5: Maoni Stephens - Server Background GC 这个问题可能有助于您观察.NET内存的内部工作原理: |