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

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

Используюем 11 джаву, плюс ломбок и котлин.


Вы провели крутую работу, прямо интересно было читать. Я такими знаниями ещё не обладаю. :)


Но скажите, чего ради ставить на прод 15 версию, когда она ещё не LTS, и мне кажется очевидным, что большинство болячек на ней будет в том или ином виде присутствовать? Мне видится куда выигрышней стратегия "сидеть на 11, а потом перейти на 17". Правда, на ней текстовые блоки и switch новый нельзя, да. Но стоит ли ради плюшек рисковать продом? Я не знаю.

>стоит ли ради плюшек рисковать продом
Я вот тоже. Не могу понять, каким образом текстовые блоки могут быть поводом для миграции. Те, кому они нужны прям очень-очень, давно уже и так пишут на скале или груви, и запускаются на JDK 8.

Могут быть важные фиксы? А могут и не быть. Не проще ли прочитать release notes, там же все написано? Если вы не сталкиваетесь с проблемами на условно, 1.8.0_181, как мы, то фиксы вам в общем-то и не нужны.

Тем более смигрировать приложение 24х7 вообще дорого.
>Не проще ли прочитать release notes
Не о всех фиксах пишется в release notes. О фиксе, который описан в статье, в release notes ничего не сказано
Ну, наверное такие бывают. Но вы же не хотите сказать, что его и в jira на JDK не было?

Я просто про другой подход к этому делу говорю — если у вас работающее приложение, 24х7, и вы не сталкивались с проблемами на текущей версии JDK/JRE, то вам ставить новую версию вообще говоря не нужно. Чинить вам нечего, а вот сломать она что-то вполне может. А если у вас есть проблемы — то вы их по нормальному, заводите в баг трекер тому же Ораклу, и ждете того релиза, в котором будут исправлены именно они (а не сотня других багов, которые у вас не проявляются).

Переезжать и чинить придется все равно — сейчас или через n лет, когда будет следующий LTS. А вот начать экономить копейку из-за фич и оптимизаций, которые завозят в каждую промежуточную версию, лучше сейчас, чем через n лет. Вполне прагматично.

Ну, хотя это логично но не всегда можно. И нужно. Вот прям если не лень — можете мне назвать список фич, которые были внедрены с Java 8 — и я вам отвечу, почему для меня они не актуальны. Потому что я это рассматриваю каждую версию, начиная с 9 — и ни одной фичи пока не нашел. Не, одну могу назвать — GC все время улучшается. Это можно было бы рассмотреть.

И если вы посмотрите опрос — то таких как я, на 8, еще 20%.

А если посчитать эти же проценты скажем в ядрах CPU — то я подозреваю, что один наш хадуп стоит десятка компаний поменьше.

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

Вот, посмотрите скажем сюда. И вы тут увидите, что поддерживается только 11. И все.

Да и у апача все примерно так же:
Supported Java Versions
Apache Hadoop 3.3 and upper supports Java 8 and Java 11 (runtime only)
Please compile Hadoop with Java 8. Compiling Hadoop with Java 11 is not supported: HADOOP-16795 — Java 11 compile support OPEN
Apache Hadoop from 3.0.x to 3.2.x now supports only Java 8
Apache Hadoop from 2.7.x to 2.10.x support both Java 7 and 8


Ну так и куда сейчас на 15? Это просто невозможно.

Ну джава, к счастью, не заканчивается на хадупе. Те, кто держит большие флоты в облаках для работы своих 24/7 сервисов, будут рады каждому сэкономленному метру памяти и каждой миллисекунде уменьшающегося latency. В зависимисти от масштаба, разница в стоимости виртуального железа на месяц или год может многократно покрыть стоимость перехода, который делается один раз и не очень долго.


Вот прям если не лень — можете мне назвать список фич, которые были внедрены с Java 8

Могу перечислить то, из-за отсутствия чего лично я вынужден придумывать многоэтажные костыли уже несколько месяцев: VarHandles (9), нормальный HttpClient на NIO (11), absolute bulk read/write для ByteBuffer (14).

>Ну джава, к счастью, не заканчивается на хадупе.
Так я и не имел в виду, что заканчивается. Я скорее это как реальный пример, когда есть в наличии большие кластера, десятки тысяч ядер, и их просто так нельзя мигрировать, некуда. Конечно, есть и другие варианты, и с ними все может быть сильно проще.

>HttpClient на NIO (11) — а разве это нельзя реализовать самому? Или там под капотом какие-то низкоуровневые фичи? Ну в смысле — костыли это понятно, неохота, но если они возможны — то это вполне может быть дешевле миграции. Вот для меня примерно так это и обстоит. Ну то есть это — как те же текстовые блоки, хорошо конечно, что они появились — но я пишу на скале и груви, и у меня они по факту всегда были, сколько помню.
HttpClient на NIO (11) — а разве это нельзя реализовать самому?

Можно, но довольно трудозатратно. Да и зачем, если вот он уже написан. Через несколько лет, он уже будет в каждом утюге, но конкретно сегодня 30-40% людей все еще сидят на 8, к сожалению.


Ну в смысле — костыли это понятно, неохота, но если они возможны — то это вполне может быть дешевле миграции.

Это же не просто костыли, это тормозные костыли. Локи вместо CAS, массивы байтов в хипе вместо direct buffers.

Ну как бы трудозатратно — это один раз. Хотя да, я охотно верю, что в условном спарке где-то в потрохах ускорение HTTP клиента могло бы дать ой какой хороший профит… но это всеж другая история слегка.
я проверял на винде, локально map-reduce и spark 2.4 работают на java 15. т.е. что-то делать сейчас на 8, что бы потом переделывать, смысла нет. следующий хадуп уже не запуститься на 8.
Ну, одно дело — это локально проверить, что оно вообще запустилось. А рискнуть десятками петабайт на дисках прома — все же немного другое. Тут лучше подготовиться.

> следующий хадуп уже не запуститься на 8.
У нас текущий cloudera 5.14 (2.6). Следующий cloudera 7.1 не просто запускается, но и рекомендует 1.8 все равно. И самосборный 3.3 тоже пока на 1.8 живет, только OpenSDK вроде.
у нас миграция с cloudera 5.x на 6.x заняла более года. когда мы будем готовы запустить что-то на кластере уже java 20 будет деприкатед, а клаудера будет мертва.
У нас 5.х -> 7.х в планах (на этот год). И я думаю с полгода оно вполне может занять (но отдельный наш проект надеюсь уложится в месяц). Некоторые команды уже смигрировали, кластер разработки функционирует — но мигрируем мы пока все равно на Java 8, чтобы минимизировать объем работ.
Хм. Вот у меня есть реальный баг в спарке, который мне мешает, вот такой. Вы хотите сказать, что достаточно запустить спарк на Java 11, и мне покажут, какая конкретно переменная? Ой что-то я не верю в это. Это вообще фича компилятора, или JVM?

JDK 14, не 11 и в ней эта фича по умолчанию отключена.


Если этот баг вам мешает и, судя по комментариям к багрепорту, известны способы его воспроизведения, почему бы не поправить его самому? Нужны только отладчик и желание.


Это фича JVM и про это английским по белому написано в этом JEP. Для лучшего эффекта class-файлы с проблемным кодом стоит собрать с полной отладочной информацией. Для javac это параметр -g.

>Нужны только отладчик и желание.
Ну, не совсем. Спарк не настолько простая фигня, чтобы это можно было сделать скажем за 30 минут. Если это происходит в распределенной среде, уже подцепиться отладчиком не совсем тривиальная задача, потому что вы не знаете в общем случае, на каком узле все будет происходить.

>Для javac это параметр -g.
Ну т.е. компилятор любой версии, но с отладкой? Впрочем, мне это вряд ли поможет, пока что никакой хадуп не поддерживает Java 14. И это не javac, а скала (но это уже мелочи).

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

Если в исходниках написано x().y().i = 99;, то для вникания придётся ещё вникнуть во все возможные детали реализации x и y (а в скале — ещё и в i), что и когда они могут возвращать, а если это интерфейсы, то проще сразу с отладчиком влезть, чем вручную выполнять весь этот код в голове.
И вот тут-то JEP 358 и должен помочь, потому что призван по крайней мере ограничить круг поиска одним конкретным местом, так как сразу будет ясно, что именно вернуло неожиданное значение. А вот так чтобы всё сразу показали — ну, серебряных пуль не бывает, но из этого никак не следует, что нет смысла даже и пытаться.

Вы преувеличиваете.

def toCatalystDecimal(hdoi: HiveDecimalObjectInspector, data: Any): Decimal = {
    if (hdoi.preferWritable()) {
      Decimal(hdoi.getPrimitiveWritableObject(data).getHiveDecimal().bigDecimalValue,
        hdoi.precision(), hdoi.scale())
    } else {
      Decimal(hdoi.getPrimitiveJavaObject(data).bigDecimalValue(), hdoi.precision(), hdoi.scale())
    }
  }


Вот что падает. Тут вполне очевидно, что именно null. Ну или во всяком случае, подозреваемый вполне явно виден. Нужно лишь пройтись по стеку, и понять, где он там по дороге таким стал.

Вы упорно не хотите понимать, что фича не является серебряной пулей, несмотря на огромную полезность.


Да, в таком коде, где вся работа ведётся с единственным суперобъектом, где лежит всё — почти все случаи ошибок будут связаны именно с суперобъектом (но всё равно не все, потому что в Java precision() может возвращать null Double, а конструктор Decimal при этом — ожидать double).


Но сводить весь язык к сугубо своим ситуациям — это путь в никуда. Вам не нужно обновляться (точнее — вы не можете, зелен виноград), потому вас никакие фичи не переубедят. Остальные обновятся.

С чего вы взяли, что я что-то не понимаю? Я вообще не спрашивал ни о чем никого, если на то пошло, а вас тем более, кроме первого вопроса. Это не моя ситуация — это ситуация в Apache Spark, каких-то мелких 28к звездочек на гитхабе, подумаешь, ерунда какая, кому он может быть интересен.

Из ответов ваших я делаю такие выводы. Потому что задачей своей вы с самого начала поставили рассмотрение всех фич в контексте "почему мне это не нужно", и именно отсюда ведёте всю аргументацию.

Очень смешно.
на жава большинство работает в серьезных канторах, соответственно не будут переделывать проекты, что бы пописать на груви или скале. а вот ради синтаксического сахарка с текстовыми блоками, var, рекордами — почему бы и нет. никто же не требует в одну ночь перевести весь проект, сервисов то много.
пока ты выявишь и углубишься в проблемы на 15, как раз и выйдет 17.
Ну почему, у нас во вполне серьезном проекте пытались тесты начать писать на котлине. В любом проекте наверное найдется такое место, где можно провести эксперимент.
Спасибо за высокую оценку!
Вы правы, стратегия обновления с LTS на LTS релевантна, но это медаль с двумя сторонами. Обновляя версии часто неминуемо будут всплывать разного рода проблемы, о которых не говорится в release notes.
И вот здесь кажется, что использовать LTS и не обновляться выгодно. Но, когда выйдет новая LTS, пусть 17-я, вам все равно придется решать проблемы промежуточных версий, и обновление займет значительно больше времени. А так получается «есть слона по частям». Вот такой путь вас может ждать при обновлении с 11 на 17-ю. Это те проблемы, которые мы решали обновляя Java:
При переходе с 11 на 14 изменились логи gc.
При переходе с 14 на 15 проблема описана в статье.
Вам придется решать эти проблемы сразу все. Основной поинт такой: чем длиннее цепочка обновлений, тем тяжелее это обновление сделать.
Это пока у вас нет условного хадупа, HBase, или другого крупного продукта, который не является вашим. Там вообще все будет иначе — вы не можете переписать продукт сами, как правило. И это будет совсем другая история.

Ну и вообще говоря, решить проблемы сразу все может оказаться проще. Ну вот смотрите, у нас в телеграмм чатике стенда разработки пасется скажем человек 500 разработчиков (точные цифры тут не важны, главное — что у нас много команд). Представим себе, что мы начали мигрировать с Java 8 (as is) скажем на Java 15. Мы наступили на разные грабли — но весьма вероятно, что разные команды на разные их виды. В итоге, одна команда, решив одну проблему, избавляет другие от повторения процесса. Зато сами стенды мы обновим один раз, а не четыре — т.е. тем кто это будет делать, задача упростится.

Ну т.е. это зависит от того, какова у вас структура компании. Не исключаю, что где-то вообще все эти проблемы решат централизованно, потому что это «одна из ключевых задач команды Архитектура» (кстати, поправьте на Архитектора, а то как-то смешно получилось :)
Немного не до конца понял мысль, можете чуть подробнее описать процесс — сколько у вас стендов и как происходит обновление?
Да тут все вполне обычно. Просто если у вас стенд разработки колхозный, на несколько команд — то вот этот вот процесс миграции Java (которая общая для всех) — он быстро не происходит. Нужно команды синхронизировать, пока последняя не проверила — дальше ехать нет особого смысла.
У нас больше сотни стендов, на которые происходит раскатка ansible-скриптами, при этом каждый сервис на стенде крутится в своем docker-контейнере со своей java. Т.е «перенести сервис на java» это не раскатать на весь стенд новую java и смотреть как все страдают, а обновить нескольких сервисах, словить ошибки и поправить. Получается как раз
В итоге, одна команда, решив одну проблему, избавляет другие от повторения процесса
Так это у вас каждое приложение в контейнере. В хадупе нельзя так, по крайней мере в 2.6. Да по-моему и в 3 тоже нельзя. Ваше приложение запустят на какой-то неизвестной вам заранее узел кластера, поэтому все JVM должны быть одинаковые. И на одной версии, поэтому же.
хадуп головного мозга, извините

так уже не мало раз упомянули, что у вас хадуп и вам от него больно, что все окружающие искреннее вам сочувствуют. НО, в мире немало и других, менее неприятных и тяжелых в обращении вещей, где попроще, посмотрите, мб вам понравится и не придется себя мучать.
«Архитектура» — это название команды. Тут все ровно :)
Кавычки добавил, спасибо)
НЛО прилетело и опубликовало эту надпись здесь

На котлине переходят не любители нового, а любители лучшего ;)

Переходите на Java 15, оно того стоит.

Переходите в клуб любителей БДСМ)

Ставить на прод свежую, еще не до конца обкатанную версию Java — это жестокий, слишком рискованный, эксперимент((( Это ладно такое, относительно безобидное, а могло бы вылезти еще что похуже…
Как можно чаще обновляйте свою Java. Это касается не только мажорных версий, но и патчевых. Там могут содержаться важные фиксы

И заодно Ubuntu в продакшене (сарказм).
Всегда должны быть первопроходцы, которые первые набьют шишек и этим помогут другим
Тут очень много пишут про LTS, но не уточняют, LTS какого вендора и на каких условиях. В проекте OpenJDK нет понятия LTS. Оно есть у Оракла за деньги и, насколько помню, у Амазона и Azul (не знаю, на каких условиях).
Ну, оракл это очевидное умолчание в данном случае. Вряд ли кто-то имел в виду конкретный амазон — не потому, что его не бывает, а просто это чуть другая история.

AdoptOpenJDK?

На прошлой работе IBM мейнфрейм используют. Туда поддержку Java11 только этим летом начали заводить ;) Вот только Traditional WebSphere всё ещё не поддерживает её :)

Большое спасибо за статью!
У меня на проекте случилось тоже самое — при обновлении с 14 на 15 увеличилось потребление памяти, ограничения на размер Code Cache не было. На тот момент просто подняли лимиты в K8s, так как ресурсы были. Сейчас тоже думаю заняться вопросом исследования потребления памяти, т.к. функционал растёт, и память хочется ограничить везде, где можно.
Также хочу высказаться в поддержку того, что гораздо проще собирать костыли в небольшом количестве раз в полгода, чем сразу много оптом. Кроме того, все эти промежуточные релизы Java — это именно релизы, полноценные, прошедшие тесты. Это ведь не Beta, где реально могут что-то сломать. А багов каждый раз фиксят много.

Не лишним будет отметить, что упомянутый багфикс уже портирован в JDK 11 (вошёл в релиз 11.0.10).

Кстати, а почему у вас такие классные базовые образы JDK с датами вместо версии?
Спасибо за уточнение! Выбрали такой способ версионирования, потому что внутри образа с JDK могут быть изменения, которые не затрагивают непосредственно изменение версии. Так что дата позволяет быстро ориентироваться среди разных сборок

Интересно. На самом деле формат версии как JDK, так и докер-образа может включать перерелизы, например:


$docker run -it bellsoft/liberica-openjdk-alpine-musl:15.0.2-10 java -version

openjdk version "15.0.2" 2021-01-19
OpenJDK Runtime Environment (build 15.0.2+10)
OpenJDK 64-Bit Server VM (build 15.0.2+10, mixed mode)
Зарегистрируйтесь на Хабре, чтобы оставить комментарий