哪里Java和.NET字符串驻留? [英] Where do Java and .NET string literals reside?
问题描述
有关字符串最近问题的文字在.NET中引起了我的眼睛。我知道,字符串是实习使不同的字符串值相同指的是同一个对象。我也知道,一个字符串,可以在运行时拘禁: P>
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屋!