Кажется, я помню, что строки в Java хранились как фактические символы вместе с началом и длиной.
Это означает, что строка подстроки может иметь одни и те же символы (поскольку они являются неизменяемыми) и должны поддерживать только начало и длину.
Так что я не совсем уверен, какие проблемы с вашей памятью имеют строки Java.
Что касается статьи, опубликованной в вашем редакторе, мне кажется, что это не проблема.
Если вы не привыкли создавать огромные струны, а затем брать из них небольшую подстроку и оставлять оставленные без присмотра, это будет иметь практически нулевое влияние на память.
Даже если у вас была строка 10M и вы создали 400 подстрок, вы используете только эти 10M для базового массива char - он не делает 400 копий этой подстроки. Единственное влияние памяти - это бит начала / длины каждого объекта подстроки.
Автор, похоже, жалуется, что они прочитали огромную строку в память, а затем хотели только ее немного, но все это было сохранено - я бы посоветовал им переосмыслить, как они обрабатывают свои данные :-)
Чтобы назвать это багом в Java, это тоже огромный шаг. Ошибка - это то, что не работает по спецификации. Это было преднамеренное дизайнерское решение для повышения производительности, нехватка памяти, потому что вы не понимаете, как все работает, это не ошибка, IMNSHO. И это определенно не утечка памяти.
В комментариях к этой статье было одно возможное хорошее предложение о том, что сборщик мусора может более агрессивно восстанавливать биты неиспользуемых строк, сжимая их.
Это , а не , что вы хотели бы сделать на первом проходе GC, поскольку это было бы относительно дорого. Однако там, где каждая другая операция GC не смогла освободить достаточно места, вы можете сделать это.
К сожалению, это почти наверняка означало бы, что базовый массив char
должен был бы хранить записи всех строковых объектов, которые ссылались на него, так что он мог бы выяснить, какие биты были не использованы и изменить все поля начала и длины строкового объекта.
Само по себе это может привести к недопустимому влиянию на производительность, и, кроме того, если вашей памяти слишком мало, чтобы это стало проблемой, вы, возможно, даже не сможете выделить достаточно места для уменьшенной версии строки.
Я думаю, что если память заканчивается, я бы предпочел, чтобы , а не поддерживал это отображение char-array-to-string, чтобы сделать возможным этот уровень GC, вместо этого я бы предпочел эту память для моих строк.
Поскольку существует совершенно приемлемый обходной путь, и хорошие кодировщики должны знать о слабостях своего языка по своему выбору, я подозреваю, что автор прав - он не будет исправлен.
Не потому, что разработчики Java слишком ленивы, а потому, что это не проблема.
Вы можете свободно применять свои собственные строковые методы, которые соответствуют методам C # (которые не разделяют базовые данные, за исключением определенных ограниченных сценариев). Это исправит проблемы с памятью, но за счет снижения производительности, поскольку вам придется копировать данные каждый раз, когда вы вызываете подстроку. Как и большинство вещей в ИТ (и жизни), это компромисс.