Pull to refresh

Comments 71

Вы какие-то монстры. Встретив бы вас ночью в серверной я бы молил о безболезненной смерти… а теперь я еще и узнал что вы некроманты.
Как теперь жить зная что меня могут оружать люди которое делают такое просто ради развлечения?

Спасибо за легкое чтиво, я теперь не усну
Раз-два, OpenJDK заберет тебя (...) никогда не спите, дети!

Правильно, нечего спать, пришло время собирать! Попробуй повторить манипуляции и собрать все у себя на локальной системе новым компилятором :)
Кровавая плата за то, что жабка самая быстрая из всех языков второго сорта (за первый примем си и плюсы).
а как же макроассемблер?
куски кода общего назначения компилятор скорее всего оптимизнет лучше человека
еще раз убеждаемся, что если бы джависты умели писать на плюсах, на них бы они и писали
В README к сборке OpenJDK указано, какими версиями тулов собирается официальный билд. Там же отмечено, что
Compilation problems with newer or different C/C++ compilers is a common problem.

Понятно, что поддержка новый версий компилятора — большая работа, сопряжённая с риском для уже проверенного кода, и никто не будет её делать для устаревающей JDK 8, поскольку это ни разу не критичная проблема.

Кстати, ещё один хинт: java -Xinternalversion скажет, каким компилятором собиралась данная конкретная версия JDK. Например, для стандартного пакета в Ubuntu это будет gcc 5.4.0. Можно сэкономить кучу времени и нервов, просто выбрав для сборки gcc-5.

$ java -Xinternalversion
OpenJDK 64-Bit Server VM (25.181-b13) for linux-amd64 JRE (1.8.0_181-8u181-b13-0ubuntu0.16.04.1-b13), built on Jul 30 2018 21:06:27 by "buildd" with gcc 5.4.0 20160609
Ну, наши-то патчи (ты помнишь какие) сейчас работают только с JDK 8, поэтому придется поддерживать все что есть, пока не портируем вперед
UFO just landed and posted this here
Во как! Стало быть, в свежей Убунте весь этот путь уже прошли. Тогда, чтобы играться с OpenJDK на Ubuntu, логичней брать исходники не с openjdk.java.net, а с launchpad.net, где все необходимые для компиляции патчи уже сделаны.
Так и у меня GCC 8 на целевой тачке. На убунте и 7.3 запустил просто чтобы покопаться кой в чем на интеле, это не конечная цель.

И кстати, вот этот образчик еще бы обсудить


char xn[10]; sprintf(xn, "x%d", j);

  • magic number,
  • отсутствие проверки на размер буфера (man snprintf),
  • отсутствие проверки на возвращаемый результат,
  • использование неправильного формата
  • и вообще использование универсальной библиотечной функции там, где должна быть специальная (itoa).

WTF. Кажется, проблема тут не с ворнингом в компиляторе, а с тем что код написан странновато.

Я понимаю твоё негодование после уймы потраченного времени ;) но по сути здесь нет никаких проблем, кроме предупреждений слишком «умного» компилятора.

  • Переменная j (индекс аргумента) на практике всегда от 0 до 3.
  • Заводить где-то отдельную константу BUFFER_SIZE для буфера, который заполняется лишь в той же строке, полагаю, перебор. Boilerplate, ничуть не улучшающий читабельность.
  • И что же делать с возвращаемым значением? Проверять, что 10 байт хватит на запись трёх символов? А если нет, то что? :) По мне так тоже перебор.
  • Что не так с форматом? И чем поможет itoa, чтобы напечатать x2?

Я ни в коем случае не хочу оспаривать паттерны написания корректного кода, но в данном конкретном примере сразу понятно, что хотел выразить автор, и что никаких багов с переполнением буфера здесь быть не может. То, что более свежий gcc стал выдавать предупреждение — да, стоит поправить, но делать из этого выводы, что написана какая-то фигня, будет преждевременно.
Времени, кстати, было потрачено минимум :-) Вот написание статьи — это да, чертова уйма времени. А еще на комментарии отвечать.
>Переменная j (индекс аргумента) на практике всегда от 0 до 3.

Тогда вообще непонятно зачем sprintsf можно было static const char* Val's[3]{«0x0»,«0x1»,«0x2»}; завести

>Заводить где-то отдельную константу BUFFER_SIZE для буфера, который заполняется лишь в той же строке, полагаю, перебор. Boilerplate, ничуть не улучшающий читабельность.

Тем что непонятно при чем тут 10 если значения 0x1,0x2,0x3 (вроде как 4 charа), код пахнет…

>Что не так с форматом? И чем поможет itoa, чтобы напечатать x2?

Тем что любая ошибка в строке форматирования это потенциальный риск stack corruption и привет rce.(я не про данный случай а вобщем).
Поэтому в современном c++ их стараются избегать.
Поэтому лучше уж либо const char xn[10]=«x»; itoa(j,xn+1,0x10); либо стримы с std::hex
Большая проблема в том, что люди думают в рамках некой «элитарной логики»: что вот этот код будут править люди, которые понимают и разбираются, и исходя из этого тут всё очевидно.

Что я понял из мира веб-программирования: код прявят ЛЮБЫЕ люди. Вполне возможно, этот человек буквально позавчера был поваром или менеджером по продажам телефонов, вчера выучил синтаксис языка и сегодня правит. Может быть это какой-то инженер, но ему очень лень разбираться, а баг надо было пофиксить ещё завтра.

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

Для этого нужно использовать не «паттерны написания корректного кода», а паттерны написания кода для последующего чтения и модификацией идиотами.

Например, если у тебя есть функция «умножь на два», то очевидно нужно использовать именно её, а не какую-то идиому состоящую из нескольких понятий. Это касается не только больших вещей вроде архитектуры, но и самых маленьких вещей.

Когда код не написан в таком стиле, мне становится плохо и больно. (В том числе и потому, что я сам ленивый идиот).
Не «паттерны написания корректного кода», а паттерны написания кода для последующего чтения и модификацией идиотами.

Просится в подзаголовок книги о Java ;)

Я серьезно собираюсь написать такую книгу или серию статей. Похоже, люди совсем обленились и не понимают, как правильно писать говнокод :-)
Подобным образом писать можно код на Java, но не на С++. Если уж ты пишешь на С++ будь добр, прочти несколько книг по некромантии, прежде чем делать что-то. Если писать «для идиотов» на С++, смысл в существовании С++ отпадает. Это язык грязных хаков и скорости, здесь не место идиотам.
вы, полагаю, удивитесь узнав, что быстродействия можно достигать и без грязных хаков, которые в свою очередь являются лишь плодом работы тех самых идиотов
Только не идиотами, а "… склонным к насилию психопатом, который знает, где вы живёте" (с)
Полностью согласен с этими тезисами, хотя и не вижу, как они относятся к данной ситуации. Как следовало написать код вместо фрагмента, который тебе так не понравился?
и вообще использование универсальной библиотечной функции там, где должна быть специальная (itoa).

itoa() не является стандартной функцией. Так что её неиспользование вполне оправдано.
UFO just landed and posted this here
Ничего не имею против std::to_string(), если проект позволяет этот стандарт.
Я имел ввиду, что старый добрый sprintf() тоже нормальное решение:
надежно, си-совместимо (кому это актуально), везде будет работать.
одно дело если бы проблемы были вызваны багами разных компиляторов тех или иных версий, а другое — баги из за того что UB в коде по разному ими интерпретируется
PS C:\Users\x> java -Xinternalversion
Java HotSpot(TM) 64-Bit Server VM (25.181-b13) for windows-amd64 JRE (1.8.0_181-b13), built on Jul 7 2018 04:01:33 by "java_re" with MS VC++ 10.0 (VS2010)

И в самом деле, некроманты.

Полагаю, что убунтоиды взяли пакет из Дебиана. А у дебиана их фирменная штабильность головного мозга :)

Ибо, в Арче:

OpenJDK 64-Bit Server VM (25.181-b13) for linux-amd64 JRE (1.8.0_181-b13), built on Aug 10 2018 18:36:50 by «builduser» with gcc 8.2.0

Вообще да, странно, на арче openjdk8 собирается без всяких патчей:
Скрытый текст
build() {
  cd jdk8u-${_repo_ver}

  unset JAVA_HOME
  # http://icedtea.classpath.org/bugzilla/show_bug.cgi?id=1346
  export MAKEFLAGS=${MAKEFLAGS/-j*}

  # We filter out -O flags so that the optimization of HotSpot is not lowered from O3 to O2
  export CFLAGS="${CFLAGS//-O2/-O3} ${CPPFLAGS} -Wno-error=deprecated-declarations -Wno-error=stringop-overflow= -Wno-error=return-type -Wno-error=cpp -fno-lifetime-dse -fno-delete-null-pointer-checks"
  export CXXFLAGS="${CXXFLAGS} ${CPPFLAGS}"

  install -d -m 755 "${srcdir}/${_prefix}/"
  sh configure \
    --prefix="${srcdir}/${_prefix}" \
    --with-update-version="${_jdk_update}" \
    --with-build-number="b${_jdk_build}" \
    --with-milestone="fcs" \
    --enable-unlimited-crypto \
    --with-zlib=system \
    --with-extra-cflags="${CFLAGS}" \
    --with-extra-cxxflags="${CXXFLAGS}" \
    --with-extra-ldflags="${LDFLAGS}"

  # TODO OpenJDK does not want last version of giflib (add 'giflib' as dependency once fixed)
  #--with-giflib=system \

  # These help to debug builds: LOG=trace HOTSPOT_BUILD_JOBS=1
  # Without 'DEBUG_BINARIES', i686 won't build: http://mail.openjdk.java.net/pipermail/core-libs-dev/2013-July/019203.html
  make
  make docs

  # FIXME sadly 'DESTDIR' is not used here!
  make install

  cd ../${_imgdir}

  # A lot of build stuff were directly taken from
  # http://pkgs.fedoraproject.org/cgit/java-1.8.0-openjdk.git/tree/java-1.8.0-openjdk.spec

  # http://icedtea.classpath.org/bugzilla/show_bug.cgi?id=1437
  find . -iname '*.jar' -exec chmod ugo+r {} \;
  chmod ugo+r lib/ct.sym

  # remove redundant *diz and *debuginfo files
  find . -iname '*.diz' -exec rm {} \;
  find . -iname '*.debuginfo' -exec rm {} \;
}

olegchir Можно вам или сообществу задать несколько вопросов по Java:
— Насколько сейчас отличается OpenJDK и OracleJDK?
— Ваше мнение о будущем одна OracleJDK?
— Например, возможно ли объединение OpenJDK + OracleJDK?
— Если да, сообщество говорит какие-либо сроки?
— Что вы думаете о использовать JDK на CentOS vs Ubuntu?
— Когда стоит переводить тест/прод на Java 11?
Спасибо
Так вроде ж нет больше никакого OracleJDK? Есть оракловская сборка с расширенной поддержкой и подпиской, для использования которй в проде нужен саппорт контракт. С тем же успехом можно взять сборочку от Azul или RedHat, которые тоже будут оказывать поддержку патчами, но на халяву.

Какой линукс используется для джавы, в целом, наплевать. Если нравится все новое — то Ubuntu, если все протухшее но стабильное — CentOS.

Переводить тест на JDK 11 нужно было вчера.
Нет, GraalVM — это совершенно отдельный продукт со своими целями, разрабатываемый в Oracle Labs.

Существует проект Metropolis: Java-on-Java. Пока он не сильно продвинулся. Полагаю, потому, что все заинтересованные (типа Джона Роуза) сейчас заняты другими делами, выпуском новой LTS версии, например :)

Вот Metropolis скорей всего будет очень сильно зависеть от того, какие открытия произойдут в ходе разработки GraalVM. В частности, в OpenJDK уже интегрирован Graal Compiler из GraalVM, являющийся единственной на данный момент поддерживаемой реализацией JVMCI в виде Java-on-Java, благодаря нему же появился AOT. Некоторые совсем новые идеи и даже драфты jep (такие как в моей прошлой статье про lazy static final поля) делаются с GraalVM в уме — lazy поля нужны в SubstrateVM, ибо новая фича по оттягиванию инициализации классов до рантайма по факту работает совсем не так как хотелось бы.

Иначе говоря, имхо, GraalVM сыграет свою роль к общей картине всего, в общем историческом процессе. Но скорей всего есть и останется отдельным специализированным продуктом.
Я говорил про JDK 11. Чем отличаются OracleJDK и OpenJDK в версиях меньше 11, скорей всего, легко гуглится. Когда я интересовался вопросом, то быстро нагуглил) Насколько помню, там разница в шрифтах и патентах на них, рендерерах в свинге и джаваэффектсах, сановских криптографических алгоритмах и прочей такой фигне. Если ты просто пишешь вебсервисы на спринге, ничего из этого тебе, скорей всего, совершенно неинтересно. Бесятся люди корпоративной шизофренией, залочиваясь на всякие платные закрытые штуки — ну вот и ладненько, лишь бы самим в этот пир духа не вписаться.

Это ea, релиза же нету ещё. Релизной oracle jdk не будет бесплатно.

ну тут речь о том, будут ли они отличаться, будет ли «Oracle JDK» как некая отдельная сущность с дополнительными фичами. То что оно будет отличаться маркетинговой дурью, стоимостью продажи колбасы и длиной очереди — можно было не сомневаться :)))
На целевой конфигурации вообще 8.2. Версия 7.3 тут только потому, что она идет из коробки в Ubuntu LTS, и лень было заморачиваться. Заморачиваться с поддержкой 8.2 будем чуть позже.
Интересно, с CLang что то подобное наблюдается или нет
Это от разработчиков больше зависит, чем от компиляторщиков. Android сейчас пользует clang 6.0.2 (притом что вышел пока только 6.0.1), но 7го пока боится…
UFO just landed and posted this here
Любой джавист в конце концов начинает писать только на C++…

Ностальгия что ли? Вот так начинаешь изучение с С++, тебя бесят указатели, вручную память выделять надо и освобождать тож, а потом берешь Java и счастье то какое — не надо всем этим заморачиваться, хотя с другой стороны получение строки с ввода выливалось в три строки кода…
вопрос скорее в назначении джавы как языка. Если ограничиваться одной технологией для всего стека задач — java хороший выбор. Но он уступает связке python/с++ (и подобным) — в качестве языка для написания performance critical кусков java в сравнении с плюсами — полумера, в качестве языка общего назначения он не проще питона.
думаю что Java — это про высокопроизводительный безопасный код, работающий в условиях высокой конкарренси и за shared mutable state. То есть, это системные вещи типа написания баз данных, про кластера, обработку Big Data, про Machine Learning, и так далее.

у Python совершенно другая ниша. Там есть некое пересечение по Machine Learning, но оно в основном работает на нативном (C/C++) коде, на питоне там только некая лайтовая обвязка. Да, Java потеряла в направлении ML преимущество, но это всё ещё починится. В отличие от питона, числодробилки можно писать на самой Java, переходя в натив только по случаю какого-то большого горя, — и это огромное конкурентное преимущество
думаю что Java — это про высокопроизводительный безопасный код, работающий в условиях высокой конкарренси и за shared mutable state

"And I write sleek performant low-overhead scala code with higher order functions that will run on anything" © Динеш, Кремниевая долина.

Сейчас 2018-й год и баззвордами никого не удивишь. А вот индуса из стереотипов они напоминают

То есть, это системные вещи типа написания баз данных, про кластера, обработку Big Data, про Machine Learning, и так далее.

и много баз данных/ML фреймворков и обработчиков Big Data написано на джаве?

В отличие от питона, числодробилки можно писать на самой Java

А зачем, если есть питон, на котором эти числодробилки уже написаны, и под капотом у них не интерпретируемый, а нативный код на си или с++?
ну как бы Hadoop — это почти синоним BigData. Говоришь BigData — подразумеваешь Hadoop. Говоришь Hadoop — подразумеваешь BigData. Spark, Tez, Hive, Impala, HBase… Есть и ML штуки вроде Mahout и MLlib, но в ML как уже говорил пока есть временные пробелы и проблемы (которые потихоньку, надеюсь, будут рассасываться).

> баззвордами

это не баззворды, а осмысленные вещи

> и под капотом у них не интерпретируемый, а нативный код на си или с++?

2018 год на дворе, Java уже давно насквозь нативная, сейчас даже генерацию exe файлов пилят
более того, нативный компилятор Java переписывают на Java, чтобы там была «Java до самого низу». Всё что мы тут обсуждаем с какими-то правками UB в C++ будет потихоньку исчезать, и надеюсь через 10 лет кода на C/C++ мы в компиляторе почти уже не увидим. В новом компиляторе нативный код приемлемо писать на чистом Си.
Похоже, я погорячился с BigData, а вы с ML.

более того, нативный компилятор Java переписывают на Java, чтобы там была «Java до самого низу»

Да, потому что java community проще поддерживать java-код, а не потому что «быстрее, выше, сильнее».
UFO just landed and posted this here
берешь Java и счастье то какое

да тоже то еще счастье)
UFO just landed and posted this here
Уже 7 лет как не рекомендуется почти что официально, и не рекомендовалось долгое время и до того

ага, в плюсах RAII — это, в общем-то, наше все. Кто в плюсах напишет явно delete (ну кроме очень узкого количества случаев), тот, в общем, нехорошо сделает
For an object of non-POD class type… before the constructor begins execution… referring to any non-static member or base class of the object results in undefined behavior

Чуть тупил в этом месте, поэтому хочу разжевать, вдруг ещё кому пригодится.


В нашем примере (оригинальный код не осиливал) переменная _b является как раз static. Также она определена после a (форвард-объявление в классе не считается), находясь в той же самой единице трансляции (.cpp-файле). Следовательно, _b всегда будет строиться после a, это вполне определено, и именно поэтому у нас срабатывает оптимизация.


Более того, поскольку _b у нас статитическая, в ней будет не мусор, а нули. Это тоже гарантировано.


Соответственно, если метод .Show() действительно детерминированно не падает на залитом нулями объекте, то без оптимизации оно могло "стабильно" работать, пусть и неправильно.


Ну и, казалось бы, если компилятор знает, что здесь точно 100% UB, то почему он не кинет предупреждение? Поспекулирую, что основывать логику предупреждений на логике оптимизации — это общепризнанно плохая идея. Разные проходы оптимизации могут очень нетривиально взаимодействовать друг с другом, и будет получаться так, что предупреждения будут зависеть от флагов оптимизации совершенно непредсказуемым образом, что дико. Поэтому ворнинг надо реализовывать отдельно, и, видимо, ни у кого руки не дошли пока.

Большое спасибо за разбор! А я думал, никто до туда не дочитает. Хабр торт.
CFLAGS += -fno-strict-aliasing -fno-lifetime-dse -fno-delete-null-pointer-checks

C++ плохой, потому что даже разработчики JDK не умею им пользоваться.
olegchir, давай подписывайся под тезисом и можно будет расходится ;)

Это так толсто, что даже тонко :-)
А про флаги… Любовь зла — полюбишь и козла!
Что-то мне подсказывает, что если собрать OpenJDK с санитайзерами и погонять нормально, откроется немало таких интересных мест.
А вот для этого у нас даже специальный человек имеется — Andrey2008 из PVS-Studio
Прочитал с удовольствием. Следующий раз разгребая чужой код и бубня «твою-мать-ну-кто-так-пишет», буду думать еще «а не написать ли мне об этом на хабре».
Сборка прошла, сгенерированы экзешники, мы молодцы.

Я надеюсь, что это метафора?
Потому что на кроссплатформенную компиляцию не похоже.
Это сборка не прикладного java-приложения, а самой джавы — виртуальной машины итп. Логично, что исполняемые файлы виртуальной машины не будут переносимыми между платформами.
Спасибо большое) Долго искал куда там воткнуть правильно эти флаги) Только баги нашёл) Наконец-то собралось на родной системе) Ура-ура!
Не увидел в комментариях. В сборке JDK9+ добавили флаг
--disable-warnings-as-errors
Который делает именно это: не включает режим «предупреждения-как-ошибки».

Ну а в целом — да. Продвинутые джава-программисты в будущем станут еще и С++-программистами. Graal, Panama и всё вокруг будет приятно располагать. Нет, С++ сейчас совсем не такой страшный, каким был во времена создания Java. Это будет просто новый уровень погружения в технологию, который многие захотят пройти.
Sign up to leave a comment.