Где находятся строковые литералы Java и .NET?

Мое внимание привлек недавний вопрос о строковых литералах в .NET. Я знаю, что строковые литералы - это интернированный, поэтому разные строки с одинаковым значением относятся к одному и тому же объекту. Я также знаю, что строку можно интернировать во время выполнения:

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

Очевидно, что строка, интернированная во время выполнения, находится в куче, но я предполагал, что литерал помещается в сегмент данных программы (и сказал об этом в моем отвечать к указанному вопросу). Однако я не помню, чтобы нигде этого видел. Я предполагаю, что дело обстоит именно так, поскольку я бы сделал это именно так, и тот факт, что инструкция ldstr IL используется для получения литералов, а распределение, похоже, не происходит, похоже, поддерживает меня.

Короче говоря, где находятся строковые литералы? Это в куче, в сегменте данных или в другом месте, о котором я не подумал?


Редактировать: Если строковые литералы делать находятся в куче, когда они выделяются?

Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
28
0
9 217
7
Перейти к ответу Данный вопрос помечен как решенный

Ответы 7

Поправьте меня, если я ошибаюсь, но не все ли объекты находятся в куче, как в Java, так и в .NET?

Типы значений в .NET находятся в стеке, если они не являются частью ссылочного типа, и в этом случае они находятся в куче.

Brian Rasmussen 16.12.2008 23:23

Верно, я бы исключил типы значений из категории "объект", но опять же, я привык к Java, а не к .NET.

matt b 16.12.2008 23:23

Если типы значений достаточно малы, они могут быть даже не в стеке, а только в регистрах.

CodesInChaos 26.11.2010 18:56
Ответ принят как подходящий

Строки в .NET являются ссылочными типами, поэтому они всегда находятся в куче (даже если они интернированы). Вы можете проверить это с помощью отладчика, такого как WinDbg.

Если у вас есть класс ниже

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

И вы вызываете Foo() на экземпляре, вы можете использовать WinDbg для проверки кучи.

Ссылка, скорее всего, будет храниться в регистре для небольшой программы, поэтому проще всего найти ссылку на конкретную строку, выполнив !dso. Это дает нам адрес нашей рассматриваемой строки:

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, чтобы узнать, в каком поколении находится экземпляр:

0:000> !gcgen 025d2d04 
Gen 0

Он находится в нулевом поколении, то есть только что был выделен. Кто его укореняет?

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 - это стек для нашего метода Foo(), но обратите внимание, что у нас также есть object[]. Это таблица стажеров. Давайте взглянем.

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

Я немного уменьшил производительность, но вы поняли идею.

В заключении: строки находятся в куче, даже если они интернированы. Интернированная таблица содержит ссылку на экземпляр в куче. Т.е. интернированные строки не собираются во время сборки мусора, потому что интернированная таблица их корни.

В .Net строковые литералы, когда они «интернированы», хранятся в специальной структуре данных, называемой «внутренней таблицей». Это отдельно от кучи и стека. Однако не все строки интернированы ... Я почти уверен, что те, которые не хранятся в куче.

Не знаю о Java

Конечно, внутренняя таблица просто содержит ссылки на строки и не хранит фактические байты, составляющие строку?

Motti 16.12.2008 23:27

Интернированная таблица содержит ссылки на строки в куче.

Brian Rasmussen 16.12.2008 23:30

В Java (из Глоссарий Java):

In Sun’s JVM, the interned Strings (which includes String literals) are stored in a special pool of RAM called the perm gen, where the JVM also loads classes and stores natively compiled code. However, the intered Strings behave no differently than had they been stored in the ordinary object heap.

Необходимо найти нормативную ссылку. Вы не можете просто цитировать или цитировать произвольный интернет-мусор.

user207421 28.06.2015 11:28

В Java строки, как и все объекты, находятся в куче. В стеке находятся только локальные примитивные переменные (целые числа, символы и ссылки на объекты).

Я нашел это на сайте MSDN о Инструкция ldstr IL:

The ldstr instruction pushes an object reference (type O) to a new string object representing the specific string literal stored in the metadata. The ldstr instruction allocates the requisite amount of memory and performs any format conversion required to convert the string literal from the form used in the file to the string format required at runtime.

The Common Language Infrastructure (CLI) guarantees that the result of two ldstr instructions referring to two metadata tokens that have the same sequence of characters return precisely the same string object (a process known as "string interning").

Это означает, что строковые литералы фактически хранятся в куче в .NET (в отличие от Java как указал от mmyers).

нет, он только говорит, что они ведут себя так же, как если бы они хранились в обычной куче

Ian Ringrose 15.01.2010 16:46

Интернированные строки в java расположены в отдельном пуле, называемом пулом строк. Этот пул поддерживается классом String и находится в обычной куче (а не в пермском пуле, как упоминалось выше, который используется для хранения данных класса).

Насколько я понимаю, не все строки интернированы, но вызов myString.intern () возвращает строку, которая гарантирована из пула строк.

Смотрите также: http://www.javaranch.com/journal/200409/ScjpTipLine-StringsLiterally.html и javadoc http://java.sun.com/j2se/1.5.0/docs/api/java/lang/String.html#intern ()

В случае буквальных строк он поддерживается компилятором и загрузчиком классов. Когда-то это действительно было в PermGen.

user207421 28.06.2015 10:43

Другие вопросы по теме