Это вопрос, который мы с трудом понимаем. Это сложно описать с помощью текста, но я надеюсь, что суть будет понята.
Я понимаю, что фактическое содержимое строки заключено во внутренний массив символов. В обычных случаях размер оставшейся кучи строки будет включать 40 байтов плюс размер массива символов. Это объясняется здесь . При вызове подстроки массив символов сохраняет ссылку на исходную строку, и, следовательно, сохраненный размер массива символов может быть намного больше, чем сама строка.
Однако при профилировании использования памяти с использованием Yourkit или MAT происходит нечто странное. Строка, которая ссылается на оставшийся размер массива char, не включает оставшийся размер массива символов.
Примером может быть следующий (полупсевдокод):
String date = "2011-11-33"; (24 bytes)
date.value = char{1172}; (2360 bytes)
Сохраняемый размер строки определяется как 24 байта без учета сохраненного размера массива символов. Это может иметь смысл, если имеется много ссылок на массив символов из-за множества операций с подстрокой.
Теперь, когда эта строка включена в некоторый тип коллекции, такой как массив или список, тогда сохраненный размер этого массива будет включать оставшийся размер всех строк, включая сохраненный размер массива символов.
У нас возникает такая ситуация:
Array's retained size = 300 bytes
array[0] = String 40 bytes;
array[1] = String 40 bytes;
array[1].value = char[] (220 bytes)
Поэтому вам нужно изучить каждую запись массива, чтобы попытаться определить, откуда берется оставшийся размер.
Опять же, это можно объяснить тем, что массив содержит все строки, которые содержат ссылки на один и тот же символьный массив, и, следовательно, в целом сохраненный размер массива является правильным.
Теперь мы подошли к проблеме.
Я храню в отдельном объекте ссылку на массив, который я обсуждал выше, а также другой массив с теми же строками. В обоих массивах строки ссылаются на один и тот же массив символов. Это ожидаемо - ведь речь идет об одной и той же строке. Однако оставшийся размер этого символьного массива учитывается для обоих массивов в этом новом объекте. Другими словами, оставшийся размер кажется двойным. Если я удаляю первый массив, то второй массив все равно будет содержать ссылку на массив символов и наоборот. Это вызывает путаницу, так как кажется, что java содержит две отдельные ссылки на один и тот же массив символов. Как это может быть? Это проблема с памятью Java или это просто способ, которым профилировщики отображают информацию?
Эта проблема вызвала у нас много головной боли при попытке отследить огромное использование памяти в нашем приложении.
Опять же - я надеюсь, что кто-то там сможет понять вопрос и объяснить его.
Спасибо за вашу помощь