Domanda

Un recente su stringa letterali in .NET catturato la mia attenzione. So che le stringhe letterali sono internati in modo che diverse stringhe con lo stesso valore si riferiscono allo stesso oggetto . So anche che una stringa può essere internato in fase di esecuzione:

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

Ovviamente una stringa che viene internata in fase di esecuzione risiede sul mucchio, ma ho dato per scontato che un letterale è posto nel segmento di dati del programma (e detto così nel mio risposta a tale questione). Tuttavia non ricordo di aver visto questo ovunque. Presumo che questo è il caso dal momento che è come lo farei e il fatto che l'istruzione ldstr IL viene utilizzata per ottenere letterali e non allocazione sembra prendere posto mi sembra il backup.

Per tagliare una lunga storia breve, da dove risiedono stringhe? E 'sul mucchio, il segmento di dati o di qualche posto che non ho pensato?


Modifica se le stringhe letterali do risiedere sul mucchio, quando sono loro assegnati?

È stato utile?

Soluzione

Le stringhe in .NET sono tipi di riferimento, in modo che siano sempre sul mucchio (anche quando sono internati). È possibile verificare ciò utilizzando un debugger come WinDbg.

Se avete la classe seguente

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

E si chiama Foo() su un'istanza, è possibile utilizzare WinDbg per ispezionare il mucchio.

Il riferimento molto probabilmente sarà memorizzato in un registro per un piccolo programma, in modo che il più semplice è quello di trovare il riferimento alla stringa specifica è facendo un !dso. Questo ci dà l'indirizzo della nostra stringa in questione:

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[])

Ora usare !gcgen per scoprire quale generazione l'istanza è in:

0:000> !gcgen 025d2d04 
Gen 0

E 'nella generazione di zero - cioè esso è appena essere allocato. Chi radicamento?

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)

L'ESP è lo stack per il nostro metodo object[], a meno di notare che abbiamo un <=> pure. Questa è la tabella di stagista. Diamo uno sguardo.

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

ho ridotto l'uscita un po ', ma si ottiene l'idea.

In conclusione : le stringhe sono sul mucchio - anche quando sono internati. La tabella internati contiene un riferimento all'istanza sul mucchio. Cioè stringhe internati non sono raccolti durante GC perché la tabella internati radici di loro.

Altri suggerimenti

In Java (dal Java Glossario ):

  

In JVM di Sun, le stringhe internati (che include stringhe letterali) sono memorizzati in una piscina speciale di RAM chiamato il perm gen, dove la JVM carica anche le classi e le memorizza in modo nativo compilato il codice. Tuttavia, le stringhe intered si comportano in modo diverso rispetto non fossero stati memorizzati nel mucchio oggetto ordinario.

Correggimi se sbaglio, ma non tutti gli oggetti risiedono sul mucchio, sia in Java e .NET?

In .Net, stringhe quando "internati", sono memorizzati in una struttura dati speciale chiamata, il "tavolo stagista". Questo è separata dal mucchio e lo stack. Non tutte le stringhe sono internati però ... Sono abbastanza sicuro che quelli che non sono vengono memorizzati sul mucchio.

Non so Java

Ho trovato questo sul sito di MSDN sulla ldstr istruzioni IL :

  

L'istruzione <=> spinge un riferimento a un oggetto (tipo O) a un nuovo oggetto stringa che rappresenta la stringa specifico letterale memorizzato nei metadati. L'istruzione <=> alloca la quantità necessaria di memoria ed esegue qualsiasi conversione formato richiesto per convertire la stringa letterale dal modulo utilizzato nel file nel formato stringa necessaria in fase di esecuzione.

     

Il Common Language Infrastructure (CLI) garantisce che il risultato di due istruzioni ldstr riferimento a due token di metadati che hanno la stessa sequenza di caratteri tornare esattamente lo stesso oggetto stringa (un processo noto come "stringa internato").

Questo implica che le stringhe letterali vengono infatti memorizzati sul mucchio in .NET (a differenza di Java come ha sottolineato da mmyers ).

In Java, le stringhe come tutti gli oggetti risiedono nel mucchio. Solo le variabili primitive locali (INT, i caratteri e riferimenti a oggetti) risiedono nello stack.

Internato stringa di in java si trovano in una piscina separata chiamata String Pool. Questa piscina è mantenuta dalla classe String e risiede sul mucchio normale (non la piscina Perm come menzionato sopra, che viene utilizzato per memorizzare i dati della classe).

A quanto mi risulta, non tutte le stringhe sono internati, ma myString.intern chiamando il numero () restituisce una stringa che è garantito dalla stringa Pool.

Si veda anche: http://www.javaranch.com/journal/200409/ScjpTipLine-StringsLiterally. html e il javadoc http: // java. sun.com/j2se/1.5.0/docs/api/java/lang/String.html#intern ()

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top