Как стать автором
Обновить

Комментарии 14

Насчёт бага автор погорячился. Из документации, на которую он же и ссылается.

The
* contents of the character array are copied; subsequent modification of
* the character array does not affect the newly created string.

Дальнейшее изменение массива не влияет на созданную строку. А вот пока она не создана (конструктор не завершил работу) очень даже влияет.

Скорее всего, нигде в спецификации не указано, что нельзя модифицировать аргументы конструктора пока он не отработал. Как и не указано обратное. Что ж, стоит указать.

P.S.

На HN автор тоже никаких ссылок на спецификацию не привёл. Аргумент лишь в том что баг приняли в багтрекер.

Есть неопределенное поведение, а есть определенно веселое поведение, можно добавить это в стандарт :) Вроде и не баг, но смотрится весело!

Мало ли что написано в спецификации. Когда юзер передаёт char[] в конструктор String, он ожидает, что конструктор будет работать согласно здравому смыслу. То есть как если бы String был реализован на массивах char'ов, как было в Java 8. А в Java 8 массив копировался единожды и никакого сломанного состояния это не могло вызвать.

В Java 9 же это поведение сломали: теперь массив копируется дважды. И теперь существует способ сломать строки, один из важнейших классов JDK. Раньше их нельзя было сломать, теперь - можно. Значит, это регресия. А значит, баг.

Мало ли что написано в спецификации.

Дальше не читал.

Спецификации пишутся людьми. И так же как в имплементациях тоже могут содержать ошибки. Если здравый смысл перевешивает спецификацию, то надо выбирать здравый смысл и исправлять спецификацию.

Вы считаете что это ошибка? Докажите.

Пока никто не привёл ссылку на спецификацию где бы утверждалось, что конструкторы гарантируют thread safety. Похоже что они её не гарантируют. Значит это не ошибка, а ожидаемое поведение.

Можем ли мы поправить эту "ошибку"? Почему бы и нет. Вроде и патч уже накидали. Можем ли мы изменить спецификацию и добавить гарантию thread-safety? Возможно. Но не надо голословно утверждать что это ошибка.

Имплементации могут содержать ошибки, да. Но есть механизм контроля — понятие сертификации: https://en.wikipedia.org/wiki/Technology_Compatibility_Kit#TCK_for_the_Java_platform

На практике: каждая строка джавовой спецификации (компилятор, виртуальная машина, библиотека классов, сериализация и другие) размечается и к ней привязываются тесты. Если тест к спецификации не привязать — выставляется баг против спиецификации в духе «Такое-то утверждение в таком-то абзаце доки к такому-то методу непроверяемо». И это стараются чинить.

За счёт гонок любой иммутабельный класс, конструируемый по мутабельному билдеру, можно сломать. Возможно, имеет смысл писать в документации, что билдер "is not thread safe". Но звучать это будет так же нелепо, как предупреждение в инструкции о том, что горячим утюгом можно обжечься.

Только при чём здесь билдеры? Строки конструируются из массивов, а не из билдеров.

В данном случае массив выполняет роль билдера.

А если ли способ прочитать все интернированные строки из кода приложения?

Вроде как да. Мне так же инетересно можно ли вызвать утечку памяти переполняя пул строк, они ведь оттуда не выгружаются?

Мне найти не удалось как это сделать.

А насчет переполнения - будет наверно OutOfMemory, если постараться. А если утечкой считать наличие в памяти неиспользуемых ресурсов, то раз они туда попали, значит, были хоть раз использованы, то есть это не утечка, так наверно.

Чтобы получить строку для которой выполняется s.isEmpty() && !s.equals(""), достаточно этого:

breakIt(" ").trim();

Это происходит из за того что метод trim не меняет поле coder для UTF16-строк, что логично, так как он удаляет из начала и конца строки символы с кодом меньше или равным коду пробела (20) не трогая остальные и таким образом не может повлиять на компактность строки.
PS насколько я понял большинство других методов работы со строками (если не все) делают дополнительные проверки и могут изменить coder.

Зарегистрируйтесь на Хабре, чтобы оставить комментарий