哪里Java和.NET字符串驻留? [英] Where do Java and .NET string literals reside?

查看:138
本文介绍了哪里Java和.NET字符串驻留?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有关字符串最近问题的文字在.NET中引起了我的眼睛。我知道,字符串是实习使不同的字符串值相同指的是同一个对象。我也知道,一个字符串,可以在运行时拘禁:

A recent question about string literals in .NET caught my eye. I know that string literals are interned so that different strings with the same value refer to the same object. I also know that a string can be interned at runtime:

string now = DateTime.Now.ToString().Intern(); 

显然被扣留在运行时字符串驻留在堆上,但我认为文字是摆在程序的数据段(说所以在我的回答到上述问题)。但是我不记得看​​到这个的任何地方。我想是这样的话,因为这是我会怎么做它和事实 ldstr IL指令是用来获取文字,也没有分配似乎发生似乎又回到了我了起来。

Obviously a string that is interned at runtime resides on the heap but I had assumed that a literal is placed in the program's data segment (and said so in my answer to said question). However I don't remember seeing this anywhere. I assume this is the case since it's how I would do it and the fact that the ldstr IL instruction is used to get literals and no allocation seems to take place seems to back me up.

要削减长话短说,你在哪里字符串驻留?它是在堆上,数据段或某些-地方我都没有想到的?

To cut a long story short, where do string literals reside? Is it on the heap, the data segment or some-place I haven't thought of?

编辑:如果字符串的的驻留在堆中,当他们分配呢?

If string literals do reside on the heap, when are they allocated?

推荐答案

在.NET中的字符串是引用类型,所以他们总是在堆(他们被拘留甚至当)。您可以使用调试器进行验证,如WinDbg的。

Strings in .NET are reference types, so they are always on the heap (even when they are interned). You can verify this using a debugger such as WinDbg.

如果您有下面的类

   class SomeType {
      public void Foo() {
         string s = "hello world";
         Console.WriteLine(s);
         Console.WriteLine("press enter");
         Console.ReadLine();
      }
   }

和你打电话美孚()的一个实例,您可以使用WinDbg检查堆。

And you call Foo() on an instance, you can use WinDbg to inspect the heap.

基准将最有可能被存储在寄存器中的一个小程序,所以最简单的就是找到引用特定的字符串是做!DSO 。这就是我们的目标字符串的地址有问题:

The reference will most likely be stored in a register for a small program, so the easiest is to find the reference to the specific string is by doing a !dso. This gives us the address of our string in question:

0:000> !dso
OS Thread Id: 0x1660 (0)
ESP/REG  Object   Name
002bf0a4 025d4bf8 Microsoft.Win32.SafeHandles.SafeFileHandle
002bf0b4 025d4bf8 Microsoft.Win32.SafeHandles.SafeFileHandle
002bf0e8 025d4e5c System.Byte[]
002bf0ec 025d4c0c System.IO.__ConsoleStream
002bf110 025d4c3c System.IO.StreamReader
002bf114 025d4c3c System.IO.StreamReader
002bf12c 025d5180 System.IO.TextReader+SyncTextReader
002bf130 025d4c3c System.IO.StreamReader
002bf140 025d5180 System.IO.TextReader+SyncTextReader
002bf14c 025d5180 System.IO.TextReader+SyncTextReader
002bf15c 025d2d04 System.String    hello world             // THIS IS THE ONE
002bf224 025d2ccc System.Object[]    (System.String[])
002bf3d0 025d2ccc System.Object[]    (System.String[])
002bf3f8 025d2ccc System.Object[]    (System.String[])

现在使用 gcgen 来找出哪一代的实例是:

Now use !gcgen to find out which generation the instance is in:

0:000> !gcgen 025d2d04 
Gen 0

这是在代零 - 也就是说,它刚刚进行分配。谁是生根呢?

It's in generation zero - i.e. it has just be allocated. Who's rooting it?

0:000> !gcroot 025d2d04 
Note: Roots found on stacks may be false positives. Run "!help gcroot" for
more info.
Scan Thread 0 OSTHread 1660
ESP:2bf15c:Root:025d2d04(System.String)
Scan Thread 2 OSTHread 16b4
DOMAIN(000E4840):HANDLE(Pinned):6513f4:Root:035d2020(System.Object[])->
025d2d04(System.String)

的ESP协议栈我们美孚()的方法,但是请注意,我们有一个 [对象] 为好。这是实习生表。让我们一起来看看。

The ESP is the stack for our Foo() method, but notice that we have a object[] as well. That's the intern table. Let's take a look.

0:000> !dumparray 035d2020
Name: System.Object[]
MethodTable: 006984c4
EEClass: 00698444
Size: 528(0x210) bytes
Array: Rank 1, Number of elements 128, Type CLASS
Element Methodtable: 00696d3c
[0] 025d1360
[1] 025d137c
[2] 025d139c
[3] 025d13b0
[4] 025d13d0
[5] 025d1400
[6] 025d1424
...
[36] 025d2d04  // THIS IS OUR STRING
...
[126] null
[127] null

我降低了输出一些,但你的想法。

I reduced the output somewhat, but you get the idea.

结论:字符串堆 - 他们被拘留时也是如此。该实习表保存引用实例堆。即GC过程中不会收集拘留字符串,因为实习表根他们。

In conclusion: strings are on the heap - even when they are interned. The interned table holds a reference to the instance on the heap. I.e. interned strings are not collected during GC because the interned table roots them.

这篇关于哪里Java和.NET字符串驻留?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆