С небольшой помощью от JVM ...
ПРЕДУПРЕЖДЕНИЕ: Это решение устарело в новых версиях Java SE. См. Другие специальные решения ниже.
Если вы используете JSM HotSpot, начиная с Java 6, обновление 21, вы можете использовать эту опцию командной строки:
-XX:+UseCompressedStrings
Страница параметров JVM гласит:
Используйте байт [] для строк, которые могут быть представлены как чистый ASCII. (Введен
в Java 6, обновление 21, выпуск Performance)
ОБНОВЛЕНИЕ : эта функция была нарушена в более поздней версии и должна была быть исправлена снова в Java SE 6u25, как указано в примечаниях к выпуску 6u25 b03 (однако мы этого не делаем см. это в примечаниях к финальному выпуску 6u25 ). отчет об ошибке 7016213 не виден из соображений безопасности. Таким образом, используйте с осторожностью и проверьте в первую очередь. Как и любая опция -XX
, она считается экспериментальной и может быть изменена без особого уведомления, поэтому, вероятно, не всегда лучше не использовать ее в скрипте запуска производственного сервера.
ОБНОВЛЕНИЕ 2013-03 (благодаря комментарию Алексей Максимус ) : см. Этот связанный вопрос и его принят ответ . Вариант теперь кажется умершим. Это дополнительно подтверждается в отчете об ошибке 7129417 .
Конец оправдывает средства
Предупреждение: (некрасиво) Решения для конкретных нужд
Это немного из коробки и ниже уровня, но так как вы спросили ... не бейте мессенджера!
Ваше собственное представление строки зажигалки
Если ASCII подходит для ваших нужд, то почему бы вам просто не развернуть собственную реализацию?
Как вы упомянули, вы можете byte[]
вместо char[]
внутри. Но это еще не все.
Чтобы сделать его еще более легким, вместо того, чтобы оборачивать свои байтовые массивы в класс, почему бы просто не использовать вспомогательный класс, содержащий в основном статические методы, работающие с этими байтовыми массивами, которые вы передаете? Конечно, он будет чувствовать себя довольно C-ish, но он будет работать и сэкономит вам огромные накладные расходы, которые идут с String
объектами.
И конечно, он потерял бы некоторые приятные функциональные возможности ... если бы вы не реализовали их заново. Если они вам действительно нужны, то выбора не так много. Благодаря OpenJDK и множеству других хороших проектов, вы вполне можете развернуть свой собственный класс LiteStrings
, который работает только с параметрами byte[]
. Вам нужно будет принимать душ каждый раз, когда вам нужно вызвать функцию, но вы сэкономите кучу памяти.
Я бы порекомендовал сделать его похожим на контракт класса String
и предоставить значимые адаптеры и компоновщики для преобразования из и в String
, и вы можете также захотеть иметь адаптеры для и из StringBuffer
и StringBuilder
, а также некоторые зеркальные реализации других вещей, которые могут вам понадобиться. Определенно какая-то часть работы, но, возможно, она того стоит (см. Чуть ниже раздела «Подсчитайте!»).
Сжатие / декомпрессия на лету
Вы можете очень хорошо сжать свои строки в памяти и распаковать их на лету, когда они вам понадобятся. В конце концов, вам нужно только читать их, когда вы к ним обращаетесь, верно?
Конечно, насилие будет означать:
- более сложный (и, следовательно, менее поддерживаемый) код,
- больше вычислительной мощности,
- Требуются относительно длинные строки, чтобы сжатие было релевантным (или чтобы объединить несколько строк в одну, внедрив собственную систему хранения, чтобы сделать сжатие более эффективным).
Обе
Для полной головной боли, конечно, вы можете сделать все это:
- C-ish класс помощника,
- байтовые массивы,
- сжатый магазин на лету.
Обязательно сделайте это с открытым исходным кодом. :)
Сделай это графом!
Кстати, посмотрите эту великолепную презентацию о Построении Java-приложений с эффективным использованием памяти , написанных Н. Митчеллом и Г. Севицким: [ 2008 версия ], [ Версия 2009 ].
Из этой презентации мы видим, что 8-символьная строка пожирает 64 байта в 32-битной системе (96 для 64-битной системы !!), и большая часть из-за JVM накладные расходы. И из этой статьи мы видим, что 8-байтовый массив будет "съедать" только 24 байта : 12 байтов заголовка, 8 x 1 байт + 4 байта выравнивания).
Звучит так, как будто это может стоить того, если вы действительно манипулируете многими этими вещами (и, возможно, немного ускоряете их, поскольку вы тратите меньше времени на выделение памяти, но не цитируйте меня по этому поводу и не сравнивайте его; плюс это сильно зависит от вашей реализации).