Сегодня Java разработчики все чаще используют библиотеки для порождения Java байт-кода в рантайме. Делается это для эффективной реализации различных трюков, которые сложно или невозможно выразить на языке Javа. Когда используется Java, компилятор javac гарантирует, что на выходе получится корректный Java байт-код. Но, спускаясь на уровень непосредственно байт-кода, часто нужно самостоятельно следить за его корректностью. Иначе при загрузке порожденных классов на выходе будет j.l.VerifyError, потому что JVM посредством верификатора Java байт-кода строго следит за корректностью байт-кода, который она загружает. Таким образом, порождая байт-код, недостаточно просто знать семантику байт-кодных инструкций — нужно также знать, как работает Java byte-code верификатор, какой байт-код он считает корректным, а какой нет.
В этом докладе мы разберемся, какую миссию в JVM несет верификатор байт-кода, когда и как он работает, может ли повлиять на производительность вашего приложения и почему опасно его отключать.
Java SE 8 has brought lambdas, default methods, type annotations, compact profiles, etc. As a result, the Java SE platform specification was changed to reflect new features.
The session shows how the new Java 8 features have been implemented in Excelsior JET JVM, written from scratch, very different from the Oracle HotSpot JVM, but compatible with the Java SE specification.
As a result, an attendee will refresh his/her memory regarding new Java 8 features, will learn how they affected the JVM specification, how the lambda expressions are translated into Java bytecode and how they can be optimized at the JVM level.
Языку Java присущ встроенный динамизм.
Reflection, динамическая загрузка — это то, без чего современные Java приложения просто не могут существовать, поэтому существует мнение, что AOT (статическая) компиляция вряд ли применима к Java в общем случае, а там где применима не может составить конкуренцию JIT (динамической) компиляции в плане прозводительности.
В этом докладе показывается почему это не (совсем) так, при этом рассматриваются случаи,
где у статических компиляторов действительно есть определенные сложности в обработке динамической семантики Java.
Также упоминается, где статическая компиляции для Java может быть полезна.
JVM: краткий курс общей анатомии, JPoint 2016 Conference EditionNikita Lipsky
Говоря о Java, мы подразумеваем как минимум две вещи: JVM (виртуальную Java-машину) и Java-байткод, который исполняется на этой машине.
Внутреннее устройство JVM непростое, но очень важно понимать, из каких частей она состоит, какая часть за что отвечает и как это все вместе работает хотя бы в самых общих чертах. Эти знания помогут вам в понимании того, как работает ваша программа и как можно улучшить ее работу.
В этом докладе мы не будем лезть в кишки какой-то конкретной реализации JVM, однако мы покажем где у JVM кишки расположены, а также где находятся и для чего служат ее печень, сердце, почки, мозг и другие органы.
Доклад на конференциях JPoint 2016, JBreak 2016
Abstract: В Java SE 8 были добавлены лямбда-выражения, дефолтные методы, типовые аннотации, компактные профили и т.п., что привело к изменениям в спецификации Java SE платформы.
В этом докладе мы рассмотрим, как новые возможности, добавленные в Java 8, были реализованы в Excelsior JET JVM, полностью написанной с нуля, совершенно непохожей на Oracle HotSpot, но при этом совместимой со спецификацией Java SE.
В итоге, слушатель освежит в памяти, что появилось в Java 8, как это повлияло на спецификацию JVM, во что превращаются лямбда-выражения в Java байт-коде, как их можно статически оптимизировать, а также получит некоторое представление о внутреннем устройстве еще одной JVM.
В Java 9 с неизбежностью появятся модули. Кого-то это мало волнует, кого-то пугает, кто-то искренне недоумевает: зачем, ведь у нас уже больше 15 лет есть OSGi, который решает ровно те же проблемы, что и модули? Здесь мы попробуем разобраться, какие проблемы пытается решить OSGi, как он их решает и решает ли в действительности. Затем посмотрим, какие проблемы, которые пытается решить OSGi, Jigsaw совсем не решает и почему, а также какие проблемы решает и как. Ну и в конце, какие проблемы Jigsaw при этом привносит в экосистему Java и что с этим делать.
Многие разработчики не представляют, как дорого обходятся ошибки в программах. Причем я имею в виду не падения ракет и прочие катастрофы, а обыкновенное прикладное программное обеспечение. Хочется показать всю важность нахождения ошибок на самых ранних этапах. Одним из способов выявить ошибку как можно раньше является статический анализ кода. Поговорим мы не только об этом, но и о различных приемах при написании кода, которые позволят избежать множество типовых ошибок.
Java SE 8 has brought lambdas, default methods, type annotations, compact profiles, etc. As a result, the Java SE platform specification was changed to reflect new features.
The session shows how the new Java 8 features have been implemented in Excelsior JET JVM, written from scratch, very different from the Oracle HotSpot JVM, but compatible with the Java SE specification.
As a result, an attendee will refresh his/her memory regarding new Java 8 features, will learn how they affected the JVM specification, how the lambda expressions are translated into Java bytecode and how they can be optimized at the JVM level.
Языку Java присущ встроенный динамизм.
Reflection, динамическая загрузка — это то, без чего современные Java приложения просто не могут существовать, поэтому существует мнение, что AOT (статическая) компиляция вряд ли применима к Java в общем случае, а там где применима не может составить конкуренцию JIT (динамической) компиляции в плане прозводительности.
В этом докладе показывается почему это не (совсем) так, при этом рассматриваются случаи,
где у статических компиляторов действительно есть определенные сложности в обработке динамической семантики Java.
Также упоминается, где статическая компиляции для Java может быть полезна.
JVM: краткий курс общей анатомии, JPoint 2016 Conference EditionNikita Lipsky
Говоря о Java, мы подразумеваем как минимум две вещи: JVM (виртуальную Java-машину) и Java-байткод, который исполняется на этой машине.
Внутреннее устройство JVM непростое, но очень важно понимать, из каких частей она состоит, какая часть за что отвечает и как это все вместе работает хотя бы в самых общих чертах. Эти знания помогут вам в понимании того, как работает ваша программа и как можно улучшить ее работу.
В этом докладе мы не будем лезть в кишки какой-то конкретной реализации JVM, однако мы покажем где у JVM кишки расположены, а также где находятся и для чего служат ее печень, сердце, почки, мозг и другие органы.
Доклад на конференциях JPoint 2016, JBreak 2016
Abstract: В Java SE 8 были добавлены лямбда-выражения, дефолтные методы, типовые аннотации, компактные профили и т.п., что привело к изменениям в спецификации Java SE платформы.
В этом докладе мы рассмотрим, как новые возможности, добавленные в Java 8, были реализованы в Excelsior JET JVM, полностью написанной с нуля, совершенно непохожей на Oracle HotSpot, но при этом совместимой со спецификацией Java SE.
В итоге, слушатель освежит в памяти, что появилось в Java 8, как это повлияло на спецификацию JVM, во что превращаются лямбда-выражения в Java байт-коде, как их можно статически оптимизировать, а также получит некоторое представление о внутреннем устройстве еще одной JVM.
В Java 9 с неизбежностью появятся модули. Кого-то это мало волнует, кого-то пугает, кто-то искренне недоумевает: зачем, ведь у нас уже больше 15 лет есть OSGi, который решает ровно те же проблемы, что и модули? Здесь мы попробуем разобраться, какие проблемы пытается решить OSGi, как он их решает и решает ли в действительности. Затем посмотрим, какие проблемы, которые пытается решить OSGi, Jigsaw совсем не решает и почему, а также какие проблемы решает и как. Ну и в конце, какие проблемы Jigsaw при этом привносит в экосистему Java и что с этим делать.
Многие разработчики не представляют, как дорого обходятся ошибки в программах. Причем я имею в виду не падения ракет и прочие катастрофы, а обыкновенное прикладное программное обеспечение. Хочется показать всю важность нахождения ошибок на самых ранних этапах. Одним из способов выявить ошибку как можно раньше является статический анализ кода. Поговорим мы не только об этом, но и о различных приемах при написании кода, которые позволят избежать множество типовых ошибок.
Как показывает практика, повсеместное применение классического, основанного на callback’ах подхода к асинхронному программированию обычно оказывается неудобным. Для упрощения написания и поддержки сложного асинхронного кода можно использовать иной подход — с использованием сопрограмм. Он значительно сокращает объём и сложность кода, превращая код из асинхронного в синхронный.
Совсем скоро выйдет Java 9, которая готовит нам много новых и интересных вещей, таких как jshell, Process API, методы-фабрики для коллекций, мультирелизные JAR-файлы и др. Но самым главным изменением будет, конечно же, введение модулей. Модуль - это новая единица инкапсуляции, которая позволит указывать явно зависимости между программными компонентами и строго контролировать, какие public-классы доступны для других компонент, а какие нет. В этой презентации мы рассмотрим в подробностях механизм модулей Java 9, в частности, как объявляются модули и как модуляризована сама JDK, а также, какие проблемы могут встретиться при миграции приложения на Java 9.
Статический анализ кода: борьба с удорожанием ошибокAndrey Karpov
Нет смысла говорить, что "надо писать код без ошибок". Ошибки были, есть и будут. Все хорошо понимают, что ошибки следует исправлять. Люди забывают, что ошибка должна быть исправлена с минимальными временными и денежными затратами!
У вас древний проект? Все зовут его «Legacy», а вас «неудачник»? Возможно они даже смеются над вами.
Давайте взглянем на ситуацию с другого ракурса. Все (все, Карл!) успешные проекты рано или поздно превращаются в Legacy-проекты.
Я затрону тему Legacy не просто как явление, а как возможность быть постоянно в тренде, прослыть супер-спецом (даже если ты знаешь всего два фреймворка), сделать карьеру, как делать, то что ты хочешь, а не то что тебя просят. Ладно, ладно, я наврал про два фреймворка, но все остальное чистая правда. Я покажу, что вы можете творить, имея правильный подход к Legacy коду.
Суть в том, что Legacy — это не грустно/уныло/немодно, это просто/клево/весело, если с умом подойти к задаче!
http://techtalks.nsu.ru
Видеозапись: http://www.youtube.com/watch?v=blXQTBiYbzs
10 декабря 2014. AOT-компиляция Java (Никита Липский, Excelsior)
«Ahead-of-time (AOT) компиляция, или статическая компиляция, не так давно объявлена компанией Oracle как одно из нововведений Java 9 — следующего мажорного релиза Java. Это объявление вызвало разнообразную реакцию в сообществе Java-программистов: некоторые удивляются почему только сейчас, кто-то в недоумении, потому что всегда считал, что AOT-компилятор для Java не возможен теоретически из-за богатых динамических возможностей Java, многие убеждены, что AOT не нужен для Java, потому что он не может конкурировать по производительности с JIT, который использует динамический профиль исполнения для оптимизации программ на лету. В этом докладе я попробую развеять распространенные мифы, которые сложились вокруг AOT-компиляции Java, расскажу почему AOT-компиляция возможна с сохранением всех динамических особенностей Java, покажу где этот подход имеет преимущества в производительности перед динамической компиляцией (JIT) с технической точки зрения, а также обрисую для чего вообще может быть полезна AOT-компиляция для Java.»
Лекция прочитана в рамках проекта Tech Talks @NSU – серии открытых лекций о разработке ПО и карьере в IT, проводимых в Новосибирском государственном университете.
Подробности: http://techtalks.nsu.ru
Исключения C++ через призму компиляторных оптимизаций. Роман Русяев ➠ CoreHa...corehard_by
На дворе 21-й век, непроизводительная реализация обработки C++ исключений на основе setjmp/longjmp уже в прошлом. Современные компиляторы, такие как gcc и clang, используют продвинутую реализацию C++ исключений, называемую zero-cost exception handling. Но насколько действительно это zero-cost? Да, мы платим увеличением размера бинарного файла, а также в случае, когда исключение действительно выбрасывается, запуская процесс stack unwinding, вызывая деструкторы для локальных объектов и т.д. Но теряем ли мы производительность, если исключение не выбрасывается? Появляются ли какие-то ограничения на компиляторные оптимизации? В этом докладе дано описание того, каким образом С++ исключения оказывают влияние на компиляторные оптимизации. Какие оптимизации не могут быть применены в случае, если функция может бросить исключения, а какие оптимизации становится труднее применять. Примеры реализации исключений и компиляторных оптимизаций рассматриваются на базе LLVM. Доклад преследует цель дать людям понимание, когда делать сборку своего приложения с -fno-exceptions имеет смысл, а когда можно наслаждаться всеми прелестями использования C++ исключений, зная, что их код не значительно потерял в производительности по сравнению с кодом, где исключения отключены.
Что могут статические анализаторы, чего не могут программисты и тестировщикиAndrey Karpov
Одной из технологий выявления ошибок на ранних этапах является статический анализ кода. К сожалению, ряд инструментов реализуют анализ весьма поверхностно, что снижает доверие к методологии статического анализа в целом. Некоторые программисты начинают думать, что анализ кода — это нечто, базирующееся на регулярных выражениях и они сами легко найдут такие ошибки. На самом деле всё гораздо сложнее и интересней. Более того, многие ошибки невероятно сложно найти, если не использовать инструменты статического анализа кода. И в этом докладе будет продемонстрировано множество таких случаев. Послушав доклад, вы взглянете на статический анализ совсем по-новому. Дополнительно будет рассказано с чего начать, если вы захотите внедрить инструмент статического анализа в уже существующий процесс разработки.
JIT-компиляция в виртуальной машине Java (HighLoad++ 2013)aragozin
Обеспечение достойной производительности высокоуровневого языка с динамической типизацией - непростая задача. Just-in-time (JIT) компиляция - динамическая генерация машинного кода с учетом информации, собранной во время выполнения приложения - ключевой элемент производительности виртуальной машины (будь то Java, .NET или даже JavaScript). JIT-компилятор, в свою очередь, должен иметь впечатляющий набор трюков и оптимизаций, что бы компенсировать "динамизм" языка.
В докладе речь пойдет о достижениях современной JIT компиляции в целом и более подробно будут освещены особенности HotSpot JVM (бесплатной JVM от Oracle)
Сергей Шамбир, Адаптация Promise/A+ для взаимодействия между C++ и JavascriptSergey Platonov
Шаблоны — мощный инструмент, добавляющий в язык новые возможности, а программистам в команде — новые проблемы. Доклад покажет, как тщательно продуманный шаблонный код может не усложнить, а упростить жизнь и дать надёжную абстракцию межпроцессных межъязыковых асинхронных вызовов функций. С помощью шаблонов можно:
адаптировать Promise/A+ из Javascript для C++
автоматически проверять и раскладывать динамический массив аргументов на статичные аргументы функции
сделать аналог std::bind для weak_ptr.
Эти вещи будут показаны на примере взаимных вызовов между C++ и Javascript в одном приложении с помощью CEF3.
Сергій Комлач
— Android розробник в Sticky Password (Чехія).
— Головні напрямки роботи — біометрична ідентифікація, кібер-безпека, кросс-платформенні рішення.
— Досвід у сфері розробки під Мобайл понад 8 років.
— Переможець Opera Mobile Store Awards.
— Спікер та учасник: Lviv Mobile Development Day, UAMobile, Frameworks Day Android, Code'n'Coffee Khmelnitsky, Google DevFest UA.
— Засновник та лідер Google Developers Group Kremenchuk.
Ошибки, которые сложно заметить на code review, но которые находятся статичес...Andrey Karpov
Есть ошибки, которые легко прячутся от программистов на обзорах кода. Чаще всего они связаны с опечатками или недостаточным знанием тонких нюансах языка/библиотеки. Давайте посмотрим интересные примеры таких ошибок и как их можно выявить с помощью статического анализа. При этом анализаторы не конкурируют с обзорами кода или, например, юнит-тестами. Они отлично дополняют другие методологии борьбы с ошибками.
Как показывает практика, повсеместное применение классического, основанного на callback’ах подхода к асинхронному программированию обычно оказывается неудобным. Для упрощения написания и поддержки сложного асинхронного кода можно использовать иной подход — с использованием сопрограмм. Он значительно сокращает объём и сложность кода, превращая код из асинхронного в синхронный.
Совсем скоро выйдет Java 9, которая готовит нам много новых и интересных вещей, таких как jshell, Process API, методы-фабрики для коллекций, мультирелизные JAR-файлы и др. Но самым главным изменением будет, конечно же, введение модулей. Модуль - это новая единица инкапсуляции, которая позволит указывать явно зависимости между программными компонентами и строго контролировать, какие public-классы доступны для других компонент, а какие нет. В этой презентации мы рассмотрим в подробностях механизм модулей Java 9, в частности, как объявляются модули и как модуляризована сама JDK, а также, какие проблемы могут встретиться при миграции приложения на Java 9.
Статический анализ кода: борьба с удорожанием ошибокAndrey Karpov
Нет смысла говорить, что "надо писать код без ошибок". Ошибки были, есть и будут. Все хорошо понимают, что ошибки следует исправлять. Люди забывают, что ошибка должна быть исправлена с минимальными временными и денежными затратами!
У вас древний проект? Все зовут его «Legacy», а вас «неудачник»? Возможно они даже смеются над вами.
Давайте взглянем на ситуацию с другого ракурса. Все (все, Карл!) успешные проекты рано или поздно превращаются в Legacy-проекты.
Я затрону тему Legacy не просто как явление, а как возможность быть постоянно в тренде, прослыть супер-спецом (даже если ты знаешь всего два фреймворка), сделать карьеру, как делать, то что ты хочешь, а не то что тебя просят. Ладно, ладно, я наврал про два фреймворка, но все остальное чистая правда. Я покажу, что вы можете творить, имея правильный подход к Legacy коду.
Суть в том, что Legacy — это не грустно/уныло/немодно, это просто/клево/весело, если с умом подойти к задаче!
http://techtalks.nsu.ru
Видеозапись: http://www.youtube.com/watch?v=blXQTBiYbzs
10 декабря 2014. AOT-компиляция Java (Никита Липский, Excelsior)
«Ahead-of-time (AOT) компиляция, или статическая компиляция, не так давно объявлена компанией Oracle как одно из нововведений Java 9 — следующего мажорного релиза Java. Это объявление вызвало разнообразную реакцию в сообществе Java-программистов: некоторые удивляются почему только сейчас, кто-то в недоумении, потому что всегда считал, что AOT-компилятор для Java не возможен теоретически из-за богатых динамических возможностей Java, многие убеждены, что AOT не нужен для Java, потому что он не может конкурировать по производительности с JIT, который использует динамический профиль исполнения для оптимизации программ на лету. В этом докладе я попробую развеять распространенные мифы, которые сложились вокруг AOT-компиляции Java, расскажу почему AOT-компиляция возможна с сохранением всех динамических особенностей Java, покажу где этот подход имеет преимущества в производительности перед динамической компиляцией (JIT) с технической точки зрения, а также обрисую для чего вообще может быть полезна AOT-компиляция для Java.»
Лекция прочитана в рамках проекта Tech Talks @NSU – серии открытых лекций о разработке ПО и карьере в IT, проводимых в Новосибирском государственном университете.
Подробности: http://techtalks.nsu.ru
Исключения C++ через призму компиляторных оптимизаций. Роман Русяев ➠ CoreHa...corehard_by
На дворе 21-й век, непроизводительная реализация обработки C++ исключений на основе setjmp/longjmp уже в прошлом. Современные компиляторы, такие как gcc и clang, используют продвинутую реализацию C++ исключений, называемую zero-cost exception handling. Но насколько действительно это zero-cost? Да, мы платим увеличением размера бинарного файла, а также в случае, когда исключение действительно выбрасывается, запуская процесс stack unwinding, вызывая деструкторы для локальных объектов и т.д. Но теряем ли мы производительность, если исключение не выбрасывается? Появляются ли какие-то ограничения на компиляторные оптимизации? В этом докладе дано описание того, каким образом С++ исключения оказывают влияние на компиляторные оптимизации. Какие оптимизации не могут быть применены в случае, если функция может бросить исключения, а какие оптимизации становится труднее применять. Примеры реализации исключений и компиляторных оптимизаций рассматриваются на базе LLVM. Доклад преследует цель дать людям понимание, когда делать сборку своего приложения с -fno-exceptions имеет смысл, а когда можно наслаждаться всеми прелестями использования C++ исключений, зная, что их код не значительно потерял в производительности по сравнению с кодом, где исключения отключены.
Что могут статические анализаторы, чего не могут программисты и тестировщикиAndrey Karpov
Одной из технологий выявления ошибок на ранних этапах является статический анализ кода. К сожалению, ряд инструментов реализуют анализ весьма поверхностно, что снижает доверие к методологии статического анализа в целом. Некоторые программисты начинают думать, что анализ кода — это нечто, базирующееся на регулярных выражениях и они сами легко найдут такие ошибки. На самом деле всё гораздо сложнее и интересней. Более того, многие ошибки невероятно сложно найти, если не использовать инструменты статического анализа кода. И в этом докладе будет продемонстрировано множество таких случаев. Послушав доклад, вы взглянете на статический анализ совсем по-новому. Дополнительно будет рассказано с чего начать, если вы захотите внедрить инструмент статического анализа в уже существующий процесс разработки.
JIT-компиляция в виртуальной машине Java (HighLoad++ 2013)aragozin
Обеспечение достойной производительности высокоуровневого языка с динамической типизацией - непростая задача. Just-in-time (JIT) компиляция - динамическая генерация машинного кода с учетом информации, собранной во время выполнения приложения - ключевой элемент производительности виртуальной машины (будь то Java, .NET или даже JavaScript). JIT-компилятор, в свою очередь, должен иметь впечатляющий набор трюков и оптимизаций, что бы компенсировать "динамизм" языка.
В докладе речь пойдет о достижениях современной JIT компиляции в целом и более подробно будут освещены особенности HotSpot JVM (бесплатной JVM от Oracle)
Сергей Шамбир, Адаптация Promise/A+ для взаимодействия между C++ и JavascriptSergey Platonov
Шаблоны — мощный инструмент, добавляющий в язык новые возможности, а программистам в команде — новые проблемы. Доклад покажет, как тщательно продуманный шаблонный код может не усложнить, а упростить жизнь и дать надёжную абстракцию межпроцессных межъязыковых асинхронных вызовов функций. С помощью шаблонов можно:
адаптировать Promise/A+ из Javascript для C++
автоматически проверять и раскладывать динамический массив аргументов на статичные аргументы функции
сделать аналог std::bind для weak_ptr.
Эти вещи будут показаны на примере взаимных вызовов между C++ и Javascript в одном приложении с помощью CEF3.
Сергій Комлач
— Android розробник в Sticky Password (Чехія).
— Головні напрямки роботи — біометрична ідентифікація, кібер-безпека, кросс-платформенні рішення.
— Досвід у сфері розробки під Мобайл понад 8 років.
— Переможець Opera Mobile Store Awards.
— Спікер та учасник: Lviv Mobile Development Day, UAMobile, Frameworks Day Android, Code'n'Coffee Khmelnitsky, Google DevFest UA.
— Засновник та лідер Google Developers Group Kremenchuk.
Ошибки, которые сложно заметить на code review, но которые находятся статичес...Andrey Karpov
Есть ошибки, которые легко прячутся от программистов на обзорах кода. Чаще всего они связаны с опечатками или недостаточным знанием тонких нюансах языка/библиотеки. Давайте посмотрим интересные примеры таких ошибок и как их можно выявить с помощью статического анализа. При этом анализаторы не конкурируют с обзорами кода или, например, юнит-тестами. Они отлично дополняют другие методологии борьбы с ошибками.
http://techtalks.nsu.ru
Видеозапись: http://www.youtube.com/watch?v=blXQTBiYbzs"
10 декабря 2014. Никита Липский (Excelsior) рассказывает про AOT-компиляцию
Ahead-of-time (AOT) компиляция, или статическая компиляция, не так давно объявлена компанией Oracle как одно из нововведений Java 9 — следующего мажорного релиза Java. Это объявление вызвало разнообразную реакцию в сообществе Java-программистов: некоторые удивляются почему только сейчас, кто-то в недоумении, потому что всегда считал, что AOT-компилятор для Java не возможен теоретически из-за богатых динамических возможностей Java, многие убеждены, что AOT не нужен для Java, потому что он не может конкурировать по производительности с JIT, который использует динамический профиль исполнения для оптимизации программ на лету.
В этом докладе я попробую развеять распространенные мифы, которые сложились вокруг AOT-компиляции Java, расскажу почему AOT-компиляция возможна с сохранением всех динамических особенностей Java, покажу где этот подход имеет преимущества в производительности перед динамической компиляцией (JIT) с технической точки зрения, а также обрисую для чего вообще может быть полезна AOT-компиляция для Java.
Лекция прочитана в рамках проекта Tech Talks @NSU – серии открытых лекций о разработке ПО и карьере в IT, проводимых в Новосибирском государственном университете.
Подробности: http://techtalks.nsu.ru
Современный статический анализ кода: что умеет он, чего не умели линтерыcorehard_by
Статический анализ появился почти 40 лет назад. В своём докладе мы хотим показать, чему за это время научились статические анализаторы. Мы рассмотрим различные методики анализа, как они появлялись и какие ошибки можно найти с помощью них. Посмотрим на примеры ошибок, найденных PVS-Studio в Open Source проектах. Поговорим о том, чем статический анализатор отличается от "линтеров" и некоторых других инструментов, а также какие проблемы решает современный статический анализатор C++ кода, помимо собственно анализа кода.
Павел Беликов
@PVS-Studio, Тула, Россия
Как создать качественный статический анализаторAndrey Karpov
В докладе я расскажу о методиках достижения высокого качества продукта, которые наша команда использует при разработке статического анализатора. Упор сделаю на особенности разработки, а также на повышение качества именно анализа, то есть поиска реальных ошибок и потенциальных уязвимостей в коде.
SAST, CWE, SEI CERT и другие умные слова из мира информационной безопасностиAndrey Karpov
Поговорим о таких терминах, связанных с информационной безопасностью, как SAST, CWE, CVE, SEI CERT, DevSecOps и как они между собой связаны. Доклад ориентирован на разработчиков и знакомит их с некоторыми понятиями и стандартами кодирования, помогающими создавать надежные, безопасные приложения. Другими словами, как писать код с меньшим количеством потенциальных уязвимостей.
SAST и Application Security: как бороться с уязвимостями в кодеAndrey Karpov
Проблематика: Объёмы кода растут; Плотность ошибок растёт нелинейно; Все хотят качественный и БЕЗОПАСНЫЙ код; Старых методов контроля качества уже недостаточно.
Архитектура растущего проекта на примере ВКонтакте / Алексей Акулович (ВКонт...Ontico
В докладе я расскажу о проблемах роста, с которыми сталкивался проект как в плане доступа к БД, так и в целом. Как решали, что получалось, как (общетеоретически или практически) можно решать подобные проблемы в других проектах.
Разберем несколько реальных случаев, когда что-то шло не так.
Доклад можно рассматривать и как небольшой экскурс в развитие технической платформы ВК, и как собрание нескольких практических способов для проекта вырасти и стать надежнее.
Выполняет анализ кода на языках: C, C++, C++/CLI, C++/CX, C#. Plugin для Visual Studio 2010-2015. Интеграция с SonarQube, QtCreator, CLion, Eclipse CDT, Anjuta DevStudio и т.д. Быстрый старт (мониторинг компиляции). Прямая интеграция анализатора в системы автоматизации сборки и утилита BlameNotifier (рассылка писем). Режим автоматического анализа изменённых файлов. Почему нужны анализаторы кода?
Formal verification of operating system kernelsDenis Efremov
The speaker will share his experience of participating in projects on formal verification and analysis of access control modules for Astra Linux SE and Elbrus kernels, as well as verification of the Contiki code (OS for IoT) within the European VESSEDIA program. The speaker will disclose details about the development of formal access control models (Rodin/Event-B) and code specifications (Frama-C/ACSL), the use of static and dynamic analyzers, and the inclusion of formal analysis in the continuous integration cycle (continuous verification). Other types of work that help meet the certification requirements will also be considered.
https://standoff365.com/phdays10/schedule/development/formal-verification-of-operating-system-kernels
Приемы Сontinuous Integration при разработке приложений на CachéInterSystems CEE
Об организации автоматизированного рабочего процесса в InterSystems Caché, Лебедюк /
Implementing modern developement practices with InterSystems Caché, Eduard Lebedyuk
Approach on how make Continuous Integration development cycle with InterSystems Caché.
Caché Object Script solution for CI with Github
https://github.com/intersystems-ru/CacheGitHubCI
"Formal verification of C code" Efremov D.V.
The talk covers the issue of developing correct software applying one of the types of static code analysis. The speaker will also address the matters of using such methods, their weaknesses and limitations, as well as the results they can guarantee.
PHDays VII, PDUG section, Moscow, May 24 2017.
"Формальная верификация кода на языке Си" Ефремов Д.В.
Доклад посвящен разработке корректного программного обеспечения с применением одного из видов статического анализа кода. Будут освещены вопросы применения подобных методов, их слабые стороны и ограничения, а также рассмотрены результаты, которые они могут дать. На конкретных примерах будет продемонстрировано, как выглядят разработка спецификаций для кода на языке Си и доказательство соответствия кода спецификациям.
Доклад представлен на конференции PHDays VII (2017) 24 мая в секции PDUG.
Доклад посвящен разработке корректного программного обеспечения с применением одного из видов статического анализа кода. Будут освещены вопросы применения подобных методов, их слабые стороны и ограничения, а также рассмотрены результаты, которые они могут дать. На конкретных примерах будет продемонстрировано, как выглядят разработка спецификаций для кода на языке Си и доказательство соответствия кода спецификациям.
Similar to Верификация Java байткода: когда, как, а может отключить? (20)
Escaping The Jar hell with Jigsaw LayersNikita Lipsky
Jigsaw modules are often criticized for the lack of versioning that exists in alternative module systems for Java, such as OSGi. One of the main purposes of versioning is to solve the so called Jar Hell problem that arises when your application depends on two different versions of the same library. While Jigsaw is able to detect this conflicting situation, it won’t allow you to load both versions that are placed on the module path. However, it is not always possible to eliminate all version conflicts from your application, because other versions of the same libraries can come to your application indirectly via dependencies that you do not control. Fortunately, there is a native solution for the problem in Jigsaw called Layers. In this session, I will show what problems Jigsaw could have introduced if it had explicit versions for modules, and how Jigsaw Layers in conjunction with Jigsaw Services help to solve the Jar Hell problem safely.
JIT Versus AOT: Unity And Conflict of Dynamic and Static Compilers (JavaOne 2...Nikita Lipsky
Java has been constantly criticized for poor performance ever since its inception, but not as much in recent years. Thanks to optimizing dynamic native code compilers, Java performance today is very close to the performance of low-level languages such as C/C++. Along with dynamic compilers, static compilers for Java have been evolving as well, so there is still no clear winner between these two approaches. It is not a surprise that an AOT compiler is finally going to appear in Java 9 via JEP-295. This session’s speaker would like to dispel common myths about the old dispute over whether dynamic or static compilation is better, show that both approaches have their strengths and weaknesses, and explain why the future is the hybrid approach.
Java 9 Modules: The Duke Yet Lives That OSGi Shall DeposeNikita Lipsky
Modules appear in Java 9 at last, but why? After all, OSGi has been around for more than 15 years and serves as the foundation of many desktop, server, and IoT applications. Its authors state that OSGi solves various dependency management problems in the most powerful way - at run time.
In this session, we will explore the problems that OSGi tries to solve, understand its approach, and identify its failures. Then we will figure out which of those problems the authors of Jigsaw ignored (and why), and which ones they solved (and how). Finally, we will talk about the challenges that Jigsaw brings with itself to the Java ecosystem and what we the developers have to do about them.
https://2017.javazone.no/program/83eb9ed50ba74946ad418a3abea0467a
JIT vs. AOT: Unity And Conflict of Dynamic and Static Compilers Nikita Lipsky
Java had been constantly criticized for poor performance ever since its inception, but not so much in recent years. Thanks to optimizing dynamic native code compilers, Java performance today is very close to the performance of low level languages such as C/C++, and is even better on some classes of applications. Along with dynamic compilers, static compilers for Java have been evolving as well, so there is still no clear winner among these two approaches. It should then come as no surprise that an AOT compiler is finally going to appear even in the HotSpot JVM and OpenJDK via JEP-295, which is officially included in Java 9.
Her, I would like to dispel common myths around the old dispute on whether dynamic or static compilation is better, show that both approaches have their strengths and weaknesses, and explain why the future is the hybrid approach.
Ahead-Of-Time Compilation of Java ApplicationsNikita Lipsky
Geekout 2016 presentation.
Ahead-of-time (AOT) native compilation has been available for .NET for quite some time, whereas Java SE, while being older than .NET, still does not have a standard AOT compiler. Some people ask why, some people think that it could only work for certain limited types of Java applications, some people think that it is not needed.
The truth, however, is that a Java AOT compiler has been available for over a decade, as part of a compliant Java SE implementation called Excelsior JET, and it proved to be useful for many organizations around the world. In this session, I would like to dispel the common myths about Java AOT compilation and show where it has advantages over JIT compilation from the technical point of view.
4. Кто знает про себя ?
• Более 20 лет профессиональной карьеры
• Инициатор проекта Excelsior JET
– работал над проектом более 17 лет
– как идейный вдохновитель
– компиляторный инженер
– руководитель
– и много в каких еще ролях
• twitter: @pjBooms
4
5. Из доклада вы узнаете
1. Как и когда работает верификатор
2. Может ли верификатор байткода замедлить
исполнение программы и ее старт
3. Что бы было, если бы не было верификатора
4. Почему опасно его отключать
5. Как избежать VerifyError при порождении
байткода
5
7. Java class file
Класс файл Пример: Constant Pool
7
Версия
Constant Pool
Имя класса, модификаторы
Суперкласс, суперинтрфейсы
Поля
Методы
Атрибуты
CONSTANT_Integer: 100500
CONSTANT_Float: 3.1415
CONSTANT_String : Hello World!
CONSTANT_Class: java.lang.String
CONSTANT_FieldRef: A.field@int
CONSTANT_MethodRef: B.method(IJ)F
CONSTANT_InterfaceMethodRef: I.foo()V
8. Java class file
• Поля, методы тоже имеют атрибуты
(например, значения константных полей)
• Главный атрибут метода – это его код: Java
байт-код
8
17. Стадии загрузки класса в JVM
• Загрузка (loading)
• Линковка (linking)
• Инициализация (initializing)
Глава “5. Loading, Linking, and Initializing”
спецификации JVM
18. Процесс загрузки класса
(создание класса)
• Читается class file
– Проверяется корректность формата (может
выбросить ClassFormatError)
• Создается ран-тайм представление класса в
выделенной области памяти
– runtime constant pool in Method Area aka Meta
Space aka Permanent Generation
• Грузятся суперкласс, суперинтерфейсы
18
22. Разрешение символьных ссылок
Класс может иметь ссылки на другие классы и поля,
методы других классов
• Ленивое разрешение
– ссылки разрешаются при первом доступе
• Энергичное разрешение
– разрешаются все ссылки какие возможно
22
23. Инициализация класса
23
class A {
static int i = 10;
static String s = "Hello";
static {
System.out.println(s);
}
}
A.class
…
<clinit>:
i = 10;
s = "Hello";
System.out.println(s);
…
Вызов статического инициализатора класса
24. Порядок стадий загрузки класса*
• Класс должен быть полностью загружен прежде,
чем слинкован
• Класс должен быть полностью проверифицирован
и подготовлен, прежде чем проинициализирован
• Ошибки разрешения ссылок, должны
происходить, когда ссылка реально требуется
* Глава 5.4 Спецификации JVM
25. Порядок стадий загрузки класса*
• Класс должен быть полностью загружен прежде,
чем слинкован
• Класс должен быть полностью проверифицирован
и подготовлен, прежде чем проинициализирован
• Ошибки разрешения ссылок, должны
происходить, когда ссылка реально требуется
* Глава 5.4 Спецификации JVM
26. Порядок стадий загрузки класса*
• Класс должен быть полностью загружен прежде,
чем слинкован
• Класс должен быть полностью проверифицирован
и подготовлен, прежде чем проинициализирован
• Ошибки разрешения ссылок, должны
происходить, когда ссылка реально требуется
* Глава 5.4 Спецификации JVM
27. Порядок стадий загрузки класса*
Вывод: верификация класса происходит до того как какой-либо
байткод какого-либо метода этого класса исполнится
Loading Verification Preparation Initializing
t
Resolution
Execution
28. Порядок стадий загрузки класса*
Вывод: верификация класса происходит до того как какой-либо
байткод какого-либо метода этого класса исполнится
Loading Verification Preparation Initializing
t
Resolution
Execution
33. Статические ограничения
• байткод не пуст и короче 65536 байт
• все инструкции идут одна за другой (нет “дыр”)
• все инструкции имеют известную JVM мнемонику (opcode)
• переходы внутри байткода не выходят за его пределы и
указывают на начало инструкции (не в середину)
• локальные переменные загружаются из корректных слотов
регистра локальных переменных (не выходят за его пределы)
• И т.д.
33
34. Статические ограничения
Проверяются за два прохода:
• Строится массив инструкций, каждая инструкция имеет
адрес (смещение внутри байткода)
• Проверяется, что все переходы корректны
На выходе получается управляющий граф (CFG) байткода
метода
34
36. Структурные ограничения
• Глубина стека в каждой инструкции должна быть
определенной величины для любого пути исполнения
• При исполнении любой инструкции не должна нарушится
типовая совместимость по присваиванию (assign
compatibility).
36
37. Структурные ограничения
• Глубина стека в каждой инструкции должна быть
определенной величины для любого пути исполнения
• При исполнении любой инструкции не должна нарушится
типовая совместимость по присваиванию (assign
compatibility).
– Пример: для инструкции putstatic C.f на вершине стэка должно
лежать значение, тип которого совместим по присваиванию с
типом поля C.f (для любого пути исполнения данной инструкции)
37
38. Структурные ограничения
Структурные ограничения оперируют термином “для любого
пути исполнения”. Однако верификация байткода должна
происходить до исполнения байткода.
Вопрос: Как это возможно?
Ответ: С помощью статического потокового анализа
38
39. Структурные ограничения
Структурные ограничения оперируют термином “для любого
пути исполнения”. Однако верификация байткода должна
происходить до исполнения байткода.
Вопрос: Как это возможно?
Ответ: С помощью статического потокового анализа
39
59. Статический потоковый анализ
Статический потоковый анализ имеет дело с:
• Потоковым графом (управляющий граф программы)
• Пометками на вершинах (свойства, вычисляемые факты)
– Начальная разметка – известные факты в начале
59
60. Статический потоковый анализ
Статический потоковый анализ имеет дело с:
• Потоковым графом (управляющий граф программы)
• Пометками на вершинах (свойства, вычисляемые факты)
– Начальная разметка – известные факты в начале
• Свойства текут от вершины к вершине
60
61. Статический потоковый анализ
Статический потоковый анализ имеет дело с:
• Потоковым графом (управляющий граф программы)
• Пометками на вершинах (свойства, вычисляемые факты)
– Начальная разметка – известные факты в начале
• Свойства текут от вершины к вершине
• Свойства преобразуются на входе в вершину и сливаются
с уже имеющимися у вершины
61
63. Полурешетка свойств
Полурешетка – <L,⋀>:
x, y, z ∈ L
1. x ⋀ x = x (самоприменимость)
2. x ⋀ y = y ⋀ x (коммутативность)
3. x ⋀ (y ⋀ z) = (x ⋀ y) ⋀ z (ассоциативность)
Частичный порядок – ≤:
x ≤ y ⇔def x ⋀ y = x
x < y ⇔def x ⋀ y = x & x ≠ y
75. Потоковые функции
Пусть <L,⋀> - полурешетка свойств
f: L → L – монотонная функция:
x, y ∈ L, x ≤ y ⇒ f(x) ≤ f(y)
Свойство GKUW (Graham, Kam, Ullman, Wegman):
f – монотонная функция ⇔
x, y ∈ L: f(x⋀y) ≤ f(x)⋀f(y)
f – дистрибутивная функция ⇔def
x, y ∈ L: f(x⋀y) = f(x)⋀f(y)
76. Потоковые функции
Пусть <L,⋀> - полурешетка свойств
f: L → L – монотонная функция:
x, y ∈ L, x ≤ y ⇒ f(x) ≤ f(y)
Свойство GKUW (Graham, Kam, Ullman, Wegman):
f – монотонная функция ⇔
x, y ∈ L: f(x⋀y) ≤ f(x)⋀f(y)
f – дистрибутивная функция ⇔def
x, y ∈ L: f(x⋀y) = f(x)⋀f(y)
77. Потоковые функции
Пусть <L,⋀> - полурешетка свойств
f: L → L – монотонная функция:
x, y ∈ L, x ≤ y ⇒ f(x) ≤ f(y)
Свойство GKUW (Graham, Kam, Ullman, Wegman):
f – монотонная функция ⇔
x, y ∈ L: f(x⋀y) ≤ f(x)⋀f(y)
f – дистрибутивная функция ⇔def
x, y ∈ L: f(x⋀y) = f(x)⋀f(y)
78. Пример дистрибутивной функции
Операция преобразования типа (cast):
(Т)v
Дистрибутивная функция:
Cast(T, Tv) := T ⋀ Tv, где Tv := Type(v)
Cast(T, Tv1 ⋀ Tv2) == Cast(T, Tv1) ⋀ Cast(T, Tv2)
78
79. Пример дистрибутивной функции
Операция преобразования типа (cast):
(Т)v
Дистрибутивная функция:
Cast(T, Tv) := T < Tv ? Tv : T, где Tv := Type(v)
Cast(T, Tv1 ⋀ Tv2) == Cast(T, Tv1) ⋀ Cast(T, Tv2)
79
80. Пример дистрибутивной функции
Операция преобразования типа (cast):
(Т)v
Дистрибутивная функция:
Cast(T, Tv) := T < Tv ? Tv : T, где Tv := Type(v)
Cast(T, Tv1 ⋀ Tv2) == Cast(T, Tv1) ⋀ Cast(T, Tv2)
80
81. Постановка задачи потокового анализа
DF=<G, Env, Init, PT> - задача потокового анализа:
G := <V, E, entry ∈V > - потоковый граф
Env := <L,⋀,F> - окружение потокового анализа
Init: V → L – начальная разметка
PT: V → F - преобразователи свойств
(для вершины v ∈ V будем записывать PTv)
82. Постановка задачи потокового анализа
( MOP решение)
DF = <G = <V, E>, Env = <L,⋀,F>, Init, PT> – задача
потокового анализа
Meet-over-all-paths (пересечение по всем путям) – (желаемое)
решение задачи потокового анализа
MOP(v) = ⋀p ∈Path(v) fp (⊤),
Path(v) = {p ∈ Paths(entry, v)| v∈V}
fp ⇔def fvn
∘… ∘ fv1
, p =(v1 .. vn) ∈ Paths(v1,vn)
fv ∈F ⇔def fv(l) = PTv(l) ⋀ Init(v), l ∈L
90. Свойства MFP
Теорема Килдалла
Let DF =<G, Env = <L,⋀,F> , Init, PT>:
f ∈ F ⇒ f – дистрибутивная(!), тогда:
MFP(v) = MOP(v), v∈V
(оптимальность)
91. Теорема о неразрешимости
Не существует алгоритма, который бы строил точное
решение (MOP) для любой задачи потокового анализа:
∄A . A вычисляет MOP
DF = <G, Env, Init, PT>
(неразрешимость)
93. Верификация байткода методом вывода типов
Type inference verifier – потоковый анализатор:
• Потоковый граф – управляющий граф (CFG)
• Решетка свойств – множество StackMapFrame
• Преобразователи свойств определены для каждой
инструкции байткода, согласно их семантики
93
94. Stack Map Frame
Stack Map Frame – свойство, вычисляемое для каждой
инструкции данного байткода метода:
• Stack: глубина и типы значений на стеке
94
95. Stack Map Frame
Stack Map Frame – свойство, вычисляемое для каждой
инструкции данного байткода метода:
• Stack: глубина и типы значений на стеке
• Locals: типы локальных переменных в регистре локальных
переменных
95
96. Пример
public static int add(int a, int b) { return a + b; }
96
0: iload 0
2: iload 1
4: iadd
5: ireturn
#0
int
#1
int
97. Пример
public static int add(int a, int b) { return a + b; }
97
0: iload 0
2: iload 1
4: iadd
5: ireturn
#0
int
#1
int
int
98. Пример
public static int add(int a, int b) { return a + b; }
98
0: iload 0
2: iload 1
4: iadd
5: ireturn
#0
int
#1
int
int
int
99. Пример
public static int add(int a, int b) { return a + b; }
99
0: iload 0
2: iload 1
4: iadd
5: ireturn
#0
int
#1
int
int
100. Пример
public static int add(int a, int b) { return a + b; }
100
0: iload 0
2: iload 1
4: iadd
5: ireturn
#0
int
#1
int
101. Пример 2
class A extends C{}; class B extends C{};
public C ifcond(boolean cond, A a, B b) {return cond?a:b;}
101
0: iload_0
1: ifeq 8
4: aload_1
5: goto 9
8: aload_2
9: areturn
#0
A
#1
int
#2
B
0
4
9
8
102. Пример 2
class A extends C{}; class B extends C{};
public C ifcond(boolean cond, A a, B b) {return cond?a:b;}
102
0: iload_0
1: ifeq 8
4: aload_1
5: goto 9
8: aload_2
9: areturn int
#0
A
#1
int
#2
B
0
4
9
8
103. Пример 2
class A extends C{}; class B extends C{};
public C ifcond(boolean cond, A a, B b) {return cond?a:b;}
103
0: iload_0
1: ifeq 8
4: aload_1
5: goto 9
8: aload_2
9: areturn
#0
A
#1
int
#2
B
0
4
9
8
104. Пример 2
class A extends C{}; class B extends C{};
public C ifcond(boolean cond, A a, B b) {return cond?a:b;}
104
0: iload_0
1: ifeq 8
4: aload_1
5: goto 9
8: aload_2
9: areturn A
#0
A
#1
int
#2
B
0
4
9
8
105. Пример 2
class A extends C{}; class B extends C{};
public C ifcond(boolean cond, A a, B b) {return cond?a:b;}
105
0: iload_0
1: ifeq 8
4: aload_1
5: goto 9
8: aload_2
9: areturn
#0
A
#1
int
#2
B
A
0
4
9
8
106. Пример 2
class A extends C{}; class B extends C{};
public C ifcond(boolean cond, A a, B b) {return cond?a:b;}
106
0: iload_0
1: ifeq 8
4: aload_1
5: goto 9
8: aload_2
9: areturn
#0
A
#1
int
#2
B
0
4
9
8
107. Пример 2
class A extends C{}; class B extends C{};
public C ifcond(boolean cond, A a, B b) {return cond?a:b;}
107
0: iload_0
1: ifeq 8
4: aload_1
5: goto 9
8: aload_2
9: areturn B
#0
A
#1
int
#2
B
0
4
9
8
108. Пример 2
class A extends C{}; class B extends C{};
public C ifcond(boolean cond, A a, B b) {return cond?a:b;}
108
0: iload_0
1: ifeq 8
4: aload_1
5: goto 9
8: aload_2
9: areturn B A⋀
#0
A
#1
int
#2
B
0
4
9
8
109. Пример 2
class A extends C{}; class B extends C{};
public C ifcond(boolean cond, A a, B b) {return cond?a:b;}
109
0: iload_0
1: ifeq 8
4: aload_1
5: goto 9
8: aload_2
9: areturn C
#0
A
#1
int
#2
B
0
4
9
8
114. Пример 3
114
SD: 0
SD: 1
SD: 2
SD: 1
SD: Stack Depth
Can’t merge
SD=1 with SD=0
Not verified!
115. Верификация байткода методом вывода типов
Каждая инструкция байткода определяет преобразователь
свойств:
F(opcode): StackMapFrame -> StackMapFrame
115
117. Верификация байткода методом вывода типов
Эти преобразователи дистрибутивны!
Значит верификатор строит точное решение задачи
верификации за конечное время без исполнения байткода!
117
118. Верификация байткода методом вывода типов
Эти преобразователи дистрибутивны!
Значит верификатор строит точное решение задачи
верификации за конечное время без исполнения байткода!
Но за какое время?
118
119. Оценка сложности алгоритма MFP
Утверждение:
Если обходить потоковый граф в глубину, то временная
сложность алгоритма MFP (AMFP):
T(AMFP) = O(BL*A*|V|),
Где A – количество обратных дуг в потоковом графе
A =O(|V|), на практике A ≤ 3
120. Верификация байткода методом вывода типов
Время работы верификатора зависит от:
• Количества инструкций
• Количества циклов
• Количества локальных переменных
• Максимальной глубины стека операндов
• Высоты иерархии классов
Дорого?
120
121. Верификация байткода методом вывода типов
Время работы верификатора зависит от:
• Количества инструкций
• Количества циклов
• Количества локальных переменных
• Максимальной глубины стека операндов
• Высоты иерархии классов
Дорого?
121
123. Верификация байткода методом
проверки типов
Вопрос: Как ускорить верификатор?
Идея: А что если мы знаем MFP решение
верификатора методом вывода типов?
Bingo! Тогда нам достаточно за один проход по байткоду
проверить, что неподвижная точка (MFP)
действительно неподвижная!
(не меняется при применении преобразователей свойств инструкций)
123
124. Верификация байткода методом
проверки типов
Вопрос: Как ускорить верификатор?
Идея: А что если мы знаем MFP решение
верификатора методом вывода типов?
Bingo! Тогда нам достаточно за один проход по байткоду
проверить, что неподвижная точка (MFP)
действительно неподвижная!
(не меняется при применении преобразователей свойств инструкций)
124
125. Верификация байткода методом
проверки типов
Вопрос: Как ускорить верификатор?
Идея: А что если мы знаем MFP решение
верификатора методом вывода типов?
Bingo! Тогда нам достаточно за один проход по байткоду
проверить, что неподвижная точка (MFP)
действительно неподвижная!
(не меняется при применении преобразователей свойств инструкций)
125
126. Верификация байткода методом
проверки типов
Split Verifier aka Type checking verifier:
• У байткода версии Java 5 может быть атрибут
StackMapTable (с Java 7 обязан быть)
126
127. Верификация байткода методом
проверки типов
Split Verifier aka Type checking verifier:
• У байткода версии Java 5 может быть атрибут
StackMapTable (с Java 7 обязан быть)
• StackMapTable – это список StackMapFrame
127
128. Верификация байткода методом
проверки типов
Split Verifier aka Type checking verifier:
• У байткода версии Java 5 может быть атрибут
StackMapTable (с Java 7 обязан быть)
• StackMapTable – это список StackMapFrame
• StackMapFrame есть для каждой начальной инструкции
линейных участков байткода, кроме первого
128
129. Верификация байткода методом
проверки типов
Split aka Type checking verifier за один проход по байткоду:
• вычисляет недостающие StackMapFrame: для каждой
инструкции проверяет входящие типы, вычисляет
исходящие (переносит ниже)
• проверяет что StackMapFrame из StackMapTable атрибута
не меняются при переносе StackMapFrame из инструкций
выше (проверка неподвижности точки)
129
130. Верификация байткода методом
проверки типов
Split aka Type checking verifier за один проход по байткоду:
• вычисляет недостающие StackMapFrame: для каждой
инструкции проверяет входящие типы, вычисляет
исходящие (переносит ниже)
• проверяет что StackMapFrame из StackMapTable атрибута
не меняются при переносе StackMapFrame из инструкций
выше (проверка неподвижности точки)
130
132. Роль верификатора байткода в JVM
Вопросы:
1. Может ли верификатор байткода замедлить исполнение ?
2. Может ли верификатор байткода замедлить старт?
3. Что было бы, если бы не было верификатора байткода?
4. А что будет, если его отключить?
132
133. Роль верификатора байткода в JVM
Вопрос: Может ли верификатор байткода замедлить
исполнение?
А исполнение чего?
• Исполнение байткода метода
• Исполнение горячего кода программы
• Исполнение программы
133
134. Роль верификатора байткода в JVM
Вопрос: Может ли верификатор байткода замедлить
исполнение?
А исполнение чего?
• Исполнение байткода метода
• Исполнение горячего кода программы
• Исполнение программы
134
135. Роль верификатора байткода в JVM
Вопрос: Может ли верификатор байткода замедлить
исполнение?
А исполнение чего?
• Исполнение байткода метода
• Исполнение горячего кода программы
• Исполнение программы
135
136. Роль верификатора байткода в JVM
Вопрос: Может ли верификатор байткода замедлить
исполнение байткода метода?
Вспомним: Верификатор работает до исполнения!
Ответ: Нет!
136
137. Роль верификатора байткода в JVM
Вопрос: Может ли верификатор байткода замедлить
исполнение байткода метода?
Вспомним: Верификатор работает до исполнения байткода!
Ответ: Нет!
137
138. Роль верификатора байткода в JVM
Вопрос: Может ли верификатор байткода замедлить
исполнение байткода метода?
Вспомним: Верификатор работает до исполнения байткода!
Ответ: Нет!
138
139. Роль верификатора байткода в JVM
Вопрос: Может ли верификатор байткода замедлить
исполнение программы?
139
140. Роль верификатора байткода в JVM
Вопрос: Может ли верификатор байткода замедлить
исполнение программы?
Верификатор работает во время загрузки класса, загрузка
классов работает во время исполнения программы
140
141. Роль верификатора байткода в JVM
Вопрос: Может ли верификатор байткода замедлить
исполнение программы?
Верификатор работает во время загрузки класса, загрузка
классов работает во время исполнения программы
Ответ: вообще говоря, да
141
142. Роль верификатора байткода в JVM
Вопрос: Может ли верификатор байткода замедлить
исполнение горячего кода?
142
143. Роль верификатора байткода в JVM
Вопрос: Может ли верификатор байткода замедлить
исполнение горячего кода?
Во время исполнения горячего кода, все классы, с которым
он работает, были загружены пока код был холодным.
143
144. Роль верификатора байткода в JVM
Вопрос: Может ли верификатор байткода замедлить
исполнение горячего кода?
Во время исполнения горячего кода, все классы, с которым
он работает, были загружены пока код был холодным.
Ответ: нет
144
146. Верификатор и время старта
0
2
4
6
8
10
12
14
16
18
20
Eclipse 4.6 Cold Start Eclipse 4.6 Warm Start
verify on
verify:none
146
Время старта Eclipse 4.6 в секундах
147. Верификатор и время старта
0
10
20
30
40
50
60
70
80
90
IntellIj IDEA 2016.3 Cold Start IntellIj IDEA 2016.3 Warm Start
verify on
verify:none
147
Время старта Intellij IDEA 2016.3 в секундах
149. Роль верификатора байткода в JVM
Вопрос: Может ли верификатор байткода замедлить старт
программы?
Ответ: незначительно
149
150. Роль верификатора байткода в JVM
Вопрос: Может ли верификатор байткода замедлить старт
программы?
Ответ: незначительно
У JVM c AOT компилятором верификация на старте может не
происходить
150
152. Роль верификатора байткода в JVM
Вопрос: Что было бы, если бы не было верификатора?
Ответ: пришлось бы вставлять проверки во время исполнения:
152
153. Роль верификатора байткода в JVM
Вопрос: Что было бы, если бы не было верификатора?
Ответ: пришлось бы вставлять проверки во время исполнения:
• для инструкций работающих со стеком, проверять что стек
не пуст и не переполнится
153
154. Роль верификатора байткода в JVM
Вопрос: Что было бы, если бы не было верификатора?
Ответ: пришлось бы вставлять проверки во время исполнения:
• для инструкций работающих со стеком, проверять что стек
не пуст и не переполнится
• для того, чтобы сложить два числа проверять, что на стеке
лежат два числа
154
155. Роль верификатора байткода в JVM
Вопрос: Что было бы, если бы не было верификатора?
Ответ: пришлось бы вставлять проверки во время исполнения:
• для инструкций работающих со стеком, проверять что стек
не пуст и не переполнится
• для того, чтобы сложить два числа проверять, что на стеке
лежат два числа
Как бы быстро тогда работали Java программы?
155
156. Роль верификатора байткода в JVM
Факт: Интерпретатор не проверяет выходы за пределы стека
операндов и типовую совместимость: если надо сложить два
числа, он просто берет их со стека и складывает.
156
157. Роль верификатора байткода в JVM
Факт: Интерпретатор не проверяет выходы за пределы стека
операндов и типовую совместимость: если надо сложить два
числа, он просто берет их со стека и складывает.
Факт: JIT компилятор при генерации машинного кода тоже не
вставляет такие проверки в машинный код.
157
158. Роль верификатора байткода в JVM
Факт: Интерпретатор не проверяет выходы за пределы стека
операндов и типовую совместимость: если надо сложить два
числа, он просто берет их со стека и складывает.
Факт: JIT компилятор при генерации машинного кода тоже не
вставляет такие проверки в машинный код.
Вывод: Наличие верификатора – первопричина почему JVM
исполняет Java программы быстро!
158
159. Роль верификатора байткода в JVM
Вопрос: А что будет, если верификатор отключить?
# A fatal error has been detected by the Java Runtime Environment:
Exception in thread "main" java.lang.StackOverflowError
at test.foo(test.j)
at test.main(test.j:3)
#
# Internal Error (javaCalls.cpp:53), pid=8012, tid=16396
# guarantee(!thread->is_Compiler_thread()) failed: cannot make java calls
from the compiler
#
159
160. Роль верификатора байткода в JVM
Вопрос: А что будет, если верификатор отключить?
# A fatal error has been detected by the Java Runtime Environment:
Exception in thread "main" java.lang.StackOverflowError
at test.foo(test.j)
at test.main(test.j:3)
#
# Internal Error (javaCalls.cpp:53), pid=8012, tid=16396
# guarantee(!thread->is_Compiler_thread()) failed: cannot make java calls
from the compiler
#
# If you would like to submit a bug report, please visit:
# http://bugreport.java.com/bugreport/crash.jsp
160
161. Роль верификатора байткода в JVM
Вопрос: А что будет, если верификатор отключить?
Ответ: Отключение верификатора может приводить к
развалам JVM, что в свою очередь открывает
потенциальные дыры в безопасности.
161
162. Роль верификатора байткода в JVM
Вопрос: А что будет, если верификатор отключить?
Ответ: Отключение верификатора может приводить к
развалам JVM, что в свою очередь открывает
потенциальные дыры в безопасности.
Вывод: Наличие верификатора делает исполнение байткода
не только эффективным, но и безопасным!
162
166. ASM библиотека
ASM библиотека
• Позволяет полностью контролировать содержимое
выходных классов, байткода
• Как следствие низкоуровневая: вы работаете
непосредственно с инструкциями байткода
166
168. ASM библиотека
• Нужно знать семантику байткодных инструкций
• Легко породить неверифицируемый байткод
• ASM умеет вычислять StackMapTable атрибут
– с помощью того же потокового анализа
• Можно задавать StackMapTable атрибут руками
– для скорости; автоматическое вычисление замедляет ASM в 2 р.
168
169. ASM библиотека
• Нужно знать семантику байткодных инструкций
• Легко породить неверифицируемый байткод
• ASM умеет вычислять StackMapTable атрибут
– с помощью того же потокового анализа
• Можно задавать StackMapTable атрибут руками
– для скорости; автоматическое вычисление замедляет ASM в 2 р.
169
170. ASM библиотека
• Нужно знать семантику байткодных инструкций
• Легко породить неверифицируемый байткод
• ASM умеет вычислять StackMapTable атрибут
– с помощью того же потокового анализа
• Можно задавать StackMapTable атрибут руками
– для скорости; автоматическое вычисление замедляет ASM в 2 р.
170
171. ASM библиотека
• Нужно знать семантику байткодных инструкций
• Легко породить неверифицируемый байткод
• ASM умеет вычислять StackMapTable атрибут
– с помощью того же потокового анализа
• Можно задавать StackMapTable атрибут руками
– для скорости; автоматическое вычисление замедляет ASM в 2
раза
171
173. Библиотеки генерации байткода
Проблема: некоторые (старые) библиотеки,
манипулирующие байткодом, не умеют вычислять
StackMapFramе
В результате вы можете получить ошибку:
java.lang.VerifyError: Expecting a stackmap frame at branch
173
174. Библиотеки генерации байткода
Проблема: некоторые (старые) библиотеки,
манипулирующие байткодом, не умеют вычислять
StackMapFramе
Можно отключить Typе Checking Verifier: -XX:-UseSplitVerifier
174
175. Библиотеки генерации байткода
Проблема: некоторые (старые) библиотеки,
манипулирующие байткодом, не умеют вычислять
StackMapFramе
Можно отключить Typе Checking Verifier: -XX:-UseSplitVerifier
Тогда будет работать Type Inference Verifier
175
176. Библиотеки генерации байткода
Проблема: некоторые (старые) библиотеки,
манипулирующие байткодом, не умеют вычислять
StackMapFramе
Можно отключить Typе Checking Verifier: -XX:-UseSplitVerifier
Тогда будет работать Type Inference Verifier
– Развал JVM не случится
176
177. Библиотеки генерации байткода
Проблема: некоторые (старые) библиотеки,
манипулирующие байткодом, не умеет вычислять
StackMapFramе
Можно отключить Typе Checking Verifier: -XX:-UseSplitVerifier
Тогда будет работать Type Inference Verifier
– Но старый верификатор не знает про invokedynamic
– Случится VerifyError при использовании лямбд
177
178. Библиотеки генерации байткода
Проблема: некоторые (старые) библиотеки,
манипулирующие байткодом, не умеет вычислять
StackMapFramе
Решение: не использовать старые библиотеки.
Используя ASM, вычислять StackMapFramе самим или с
помощью ASM.
178
180. Заключение
Верификатор Java байткода:
• Незаслуженно обделенная вниманием часть JVM
• Первопричина почему JVM исполняет программы быстро
(практически на уровне низкоуровневых языков)
• Гарантирует безопасность исполнения
• Отключать верификатор не имеет никакого практического
cмысла
• Зная как работает верификатор, порождать байткод легко
180
181. Заключение
Верификатор Java байткода:
• Незаслуженно обделенная вниманием часть JVM
• Первопричина почему JVM исполняет программы быстро
(практически на уровне низкоуровневых языков)
• Гарантирует безопасность исполнения
• Отключать верификатор не имеет никакого практического
cмысла
• Зная как работает верификатор, порождать байткод легко
181
182. Заключение
Верификатор Java байткода:
• Незаслуженно обделенная вниманием часть JVM
• Первопричина почему JVM исполняет программы быстро
(практически на уровне низкоуровневых языков)
• Гарантирует безопасность исполнения
• Отключать верификатор не имеет никакого практического
cмысла
• Зная как работает верификатор, порождать байткод легко
182
183. Заключение
Верификатор Java байткода:
• Незаслуженно обделенная вниманием часть JVM
• Первопричина почему JVM исполняет программы быстро
(практически на уровне низкоуровневых языков)
• Гарантирует безопасность исполнения
• Отключать верификатор не имеет никакого практического
cмысла
• Зная как работает верификатор, порождать байткод легко
183
184. Заключение
Верификатор Java байткода:
• Незаслуженно обделенная вниманием часть JVM
• Первопричина почему JVM исполняет программы быстро
(практически на уровне низкоуровневых языков)
• Гарантирует безопасность исполнения
• Отключать верификатор не имеет никакого практического
cмысла
• Зная как работает верификатор, порождать байткод легко
184
185. Заключение
Верификатор Java байткода:
• Незаслуженно обделенная вниманием часть JVM
• Первопричина почему JVM исполняет программы быстро
(практически на уровне низкоуровневых языков)
• Гарантирует безопасность исполнения
• Отключать верификатор не имеет никакого практического
cмысла
• Зная как работает верификатор, порождать байткод легко
185