Что означает декларируемый java принцип write once run anywhere

Особенности языка Java

Что означает декларируемый java принцип write once run anywhere. Смотреть фото Что означает декларируемый java принцип write once run anywhere. Смотреть картинку Что означает декларируемый java принцип write once run anywhere. Картинка про Что означает декларируемый java принцип write once run anywhere. Фото Что означает декларируемый java принцип write once run anywhere

Что означает декларируемый java принцип write once run anywhere. Смотреть фото Что означает декларируемый java принцип write once run anywhere. Смотреть картинку Что означает декларируемый java принцип write once run anywhere. Картинка про Что означает декларируемый java принцип write once run anywhere. Фото Что означает декларируемый java принцип write once run anywhere

Что означает декларируемый java принцип write once run anywhere. Смотреть фото Что означает декларируемый java принцип write once run anywhere. Смотреть картинку Что означает декларируемый java принцип write once run anywhere. Картинка про Что означает декларируемый java принцип write once run anywhere. Фото Что означает декларируемый java принцип write once run anywhere

Язык Java был создан в 1995 году, и за 22 года своего существования покорил сердца миллионов программистов. Как ему это удалось? Почему за это время не появилось ни одной достойной замены? Чтобы разобраться в этом, поговорим об особенностях языка Java.

Компания Sun Microsystems при выпуске языка заложила 5 парадигм потенциального успеха:

Рассмотрим каждую из них подробнее.

Простота

Синтаксис языка был унаследован от C++. Сегодня на фоне Python, Groove или Go его трудно назвать простым, однако тогда эволюционный вид позволил привлечь внимание Си-разработчиков.

Стандартная программа “Hello World” выглядит следующим образом:

Такая форма конструкций не увеличивает скорость набора, однако читать, понимать и воспроизводить его просто.

Надёжность

Надёжность обеспечивается двумя принципами:

Кроме того, первоначально в Java предполагался запрет прямого доступа к памяти, что также повышало бы надёжность. Но разработчики оставили несколько лазеек, например бэкдор sun.misc.Unsafe, которые этот запрет обходят.

Безопасность

Кроме сохранения общей формы конструкций, Java по сравнению с C++ формально лишился двух потенциальных опасностей: указателей и множественного наследования. На деле обе функции сохранены, но представлены в ином виде: вместо указателей используются значения, а в множественном наследовании участвуют не классы, а интерфейсы. Тем не менее, такая особенность java программирования почти исключает возможный урон от невнимательности разработчика.

Удобство

Дословно концепция Java звучит как: «Write once, run anywhere». То есть исполняемость кода не зависит от используемой операционной системы или установленного ПО. Достигается это благодаря транслированию в байт-код виртуальной машиной JVM.

Как нельзя кстати пригодилась эта особенность java на android. Разнообразие производителей, моделей телефонов, характеристик — всё это могло бы негативно сказаться на работе приложений, если бы не существование такого универсального инструмента.

Производительность

Особенность ява, связанная с транслированием в байт-код, положительно сказывается и на производительности конечных продуктов. По скорости исполнения однотипные программы на java уступают в 1,5-2 раза программам на C/C++, при этом превосходят JavaScript, Ruby, Python.

Развитая экосистема

За 22 года жизни язык оброс десятками IDE и фреймворков, сотнями сообществ и форумов, тысячами библиотек и плагинов. Всё это благоприятно сказывается на пороге вхождения в профессию, востребованности и качеству производимых с помощью java продуктов.

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

Советуем пройти бесплатный двухдневный интенсив по основам Java и познакомиться с этим языком 🙂

Что означает декларируемый java принцип write once run anywhere. Смотреть фото Что означает декларируемый java принцип write once run anywhere. Смотреть картинку Что означает декларируемый java принцип write once run anywhere. Картинка про Что означает декларируемый java принцип write once run anywhere. Фото Что означает декларируемый java принцип write once run anywhere

Язык Java был создан в 1995 году, и за 22 года своего существования покорил сердца миллионов программистов. Как ему это удалось? Почему за это время не появилось ни одной достойной замены? Чтобы разобраться в этом, поговорим об особенностях языка Java.

Компания Sun Microsystems при выпуске языка заложила 5 парадигм потенциального успеха:

Рассмотрим каждую из них подробнее.

Простота

Синтаксис языка был унаследован от C++. Сегодня на фоне Python, Groove или Go его трудно назвать простым, однако тогда эволюционный вид позволил привлечь внимание Си-разработчиков.

Стандартная программа “Hello World” выглядит следующим образом:

Такая форма конструкций не увеличивает скорость набора, однако читать, понимать и воспроизводить его просто.

Надёжность

Надёжность обеспечивается двумя принципами:

Кроме того, первоначально в Java предполагался запрет прямого доступа к памяти, что также повышало бы надёжность. Но разработчики оставили несколько лазеек, например бэкдор sun.misc.Unsafe, которые этот запрет обходят.

Безопасность

Кроме сохранения общей формы конструкций, Java по сравнению с C++ формально лишился двух потенциальных опасностей: указателей и множественного наследования. На деле обе функции сохранены, но представлены в ином виде: вместо указателей используются значения, а в множественном наследовании участвуют не классы, а интерфейсы. Тем не менее, такая особенность java программирования почти исключает возможный урон от невнимательности разработчика.

Удобство

Дословно концепция Java звучит как: «Write once, run anywhere». То есть исполняемость кода не зависит от используемой операционной системы или установленного ПО. Достигается это благодаря транслированию в байт-код виртуальной машиной JVM.

Как нельзя кстати пригодилась эта особенность java на android. Разнообразие производителей, моделей телефонов, характеристик — всё это могло бы негативно сказаться на работе приложений, если бы не существование такого универсального инструмента.

Производительность

Особенность ява, связанная с транслированием в байт-код, положительно сказывается и на производительности конечных продуктов. По скорости исполнения однотипные программы на java уступают в 1,5-2 раза программам на C/C++, при этом превосходят JavaScript, Ruby, Python.

Развитая экосистема

За 22 года жизни язык оброс десятками IDE и фреймворков, сотнями сообществ и форумов, тысячами библиотек и плагинов. Всё это благоприятно сказывается на пороге вхождения в профессию, востребованности и качеству производимых с помощью java продуктов.

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

Советуем пройти бесплатный двухдневный интенсив по основам Java и познакомиться с этим языком 🙂

Источник

Why is Java ‘write once and run anywhere’?

JVM(Java Virtual Machine) acts as a run-time engine to run Java applications. JVM is the one that actually calls the main method present in Java code. JVM is a part of the JRE(Java Runtime Environment).

Java applications are called WORA (Write Once Run Anywhere). This means a programmer can develop Java code on one system and can expect it to run on any other Java-enabled system without any adjustment. This is all possible because of JVM.

Attention reader! Don’t stop learning now. Get hold of all the important Java Foundation and Collections concepts with the Fundamentals of Java and Java Collections Course at a student-friendly price and become industry ready. To complete your preparation from learning a language to DS Algo and many more, please refer Complete Interview Preparation Course.

In traditional programming languages like C, C++ when programs were compiled, they used to be converted into the code understood by the particular underlying hardware, so If we try to run the same code at another machine with different hardware, which understands different code will cause an error, so you have to re-compile the code to be understood by the new hardware.

In Java, the program is not converted to code directly understood by Hardware, rather it is converted to bytecode(.class file), which is interpreted by JVM, so once compiled it generates bytecode file, which can be run anywhere (any machine) which has JVM( Java Virtual Machine) and hence it gets the nature of Write Once and Run Anywhere.

Что означает декларируемый java принцип write once run anywhere. Смотреть фото Что означает декларируемый java принцип write once run anywhere. Смотреть картинку Что означает декларируемый java принцип write once run anywhere. Картинка про Что означает декларируемый java принцип write once run anywhere. Фото Что означает декларируемый java принцип write once run anywhere

Example: Practical Implementation of WORA using a simple JAVA program to check whether a number is even or odd.

Источник

Инструменты для запуска и разработки Java приложений, компиляция, выполнение на JVM

Ни для кого не секрет, что на данный момент Java — один из самых популярных языков программирования в мире. Дата официального выпуска Java — 23 мая 1995 года.

Эта статья посвящена основам основ: в ней изложены базовые особенности языка, которые придутся кстати начинающим “джавистам”, а опытные Java-разработчики смогут освежить свои знания.

* Статья подготовлена на основе доклада Евгения Фраймана — Java разработчика компании IntexSoft.
В статье присутствуют ссылки на внешние материалы
.

Что означает декларируемый java принцип write once run anywhere. Смотреть фото Что означает декларируемый java принцип write once run anywhere. Смотреть картинку Что означает декларируемый java принцип write once run anywhere. Картинка про Что означает декларируемый java принцип write once run anywhere. Фото Что означает декларируемый java принцип write once run anywhere

1. JDK, JRE, JVM

Java Development Kit — комплект разработчика приложений на языке Java. Он включает в себя Java Development Tools и среду выполнения Java — JRE (Java Runtime Environment).

Java development tools включают в себя около 40 различных тулов: javac (компилятор), java (лаунчер для приложений), javap (java class file disassembler), jdb (java debugger) и др.

Среда выполнения JRE — это пакет всего необходимого для запуска скомпилированной Java-программы. Включает в себя виртуальную машину JVM и библиотеку классов Java — Java Class Library.

JVM — это программа, предназначенная для выполнения байт-кода. Первое преимущество JVM — это принцип “Write once, run anywhere”. Он означает, что приложение, написанное на Java, будет работать одинаково на всех платформах. Это является большим преимуществом JVM и самой Java.

До появления Java, многие компьютерные программы были написаны под определенные компьютерные системы, а предпочтение отдавалось ручному управлению памятью, как более эффективному и предсказуемому. Со второй половины 1990-х годов, после появления Java, автоматическое управление памятью стало общей практикой.

Существует множество реализаций JVM, как коммерческих, так и с открытым кодом. Одна из целей создания новых JVM — увеличение производительности для конкретной платформы. Каждая JVM пишется под платформу отдельно, при этом есть возможность написать ее так, чтобы она работала быстрее на конкретной платформе. Самая распространённая реализация JVM — это JVM Hotspot от OpenJDK. Также есть реализации IBM J9, Excelsior JET.

2. Выполнение кода на JVM

Согласно спецификации Java SE, для того, чтобы получить код, работающий в JVM, необходимо выполнить 3 этапа:

3. Загрузчики классов и их иерархия

Вернемся к загрузчикам классов — это специальные классы, которые являются частью JVM. Они загружают классы в память и делают их доступными для выполнения. Загрузчики работают со всеми классами: и с нашими, и с теми, которые непосредственно нужны для Java.

Представьте ситуацию: мы написали свое приложение, и помимо стандартных классов там есть наши классы, и их очень много. Как с этим будет работать JVM? В Java реализована отложенная загрузка классов, иными словами lazy loading. Это значит, что загрузка классов не будет выполняться до тех пор, пока в приложении не встретится обращение к классу.

Иерархия загрузчиков классов

Что означает декларируемый java принцип write once run anywhere. Смотреть фото Что означает декларируемый java принцип write once run anywhere. Смотреть картинку Что означает декларируемый java принцип write once run anywhere. Картинка про Что означает декларируемый java принцип write once run anywhere. Фото Что означает декларируемый java принцип write once run anywhere

Первый загрузчик классов — это Bootstrap classloader. Он написан на C++. Это базовый загрузчик, который загружает все системные классы из архива rt.jar. При этом, есть небольшое отличие между загрузкой классов из rt.jar и наших классов: когда JVM загружает классы из rt.jar, она не выполняет все этапы проверки, которые выполняются при загрузке любого другого класс-файла т.к. JVM изначально известно, что все эти классы уже проверены. Поэтому, включать в этот архив какие-либо свои файлы не стоит.

Следующий загрузчик — это Extension classloader. Он загружает классы расширений из папки jre/lib/ext. Допустим, вы хотите, чтобы какой-то класс загружался каждый раз при старте Java машины. Для этого вы можете скопировать исходный файл класса в эту папку, и он будет автоматически загружаться.

Еще один загрузчик — System classloader. Он загружает классы из classpath’а, который мы указали при запуске приложения.

Процесс загрузки классов происходит по иерархии:

4. Структура Сlass-файлов и процесс загрузки

Перейдем непосредственно к структуре Class-файлов.

Все числа, строки, указатели на классы, поля и методы хранятся в Сonstant pool — области памяти Meta space. Описание класса хранится там же и содержит имя, модификаторы, супер-класс, супер-интерфейсы, поля, методы и атрибуты. Атрибуты, в свою очередь, могут содержать любую дополнительную информацию.

Таким образом, при загрузке классов:

5. Исполнение байт-кода на JVM

В первую очередь, для исполнения байт-кода, JVM может его интерпретировать. Интерпретация — довольно медленный процесс. В процессе интерпретации, интерпретатор “бежит” построчно по класс-файлу и переводит его в команды, которые понятны JVM.

Также JVM может его транслировать, т.е. скомпилировать в машинный код, который будет исполняться непосредственно на CPU.

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

6. Компиляция

Компилятор — это программа, которая преобразует исходные части программ, написанные на языке программирования высокого уровня, в программу на машинном языке, “понятную” компьютеру.

Компиляторы делятся на:

Также компиляторы могут классифицироваться по моменту компиляции:

7. Организация памяти в Java

Стек — это область памяти в Java, которая работает по схеме LIFO — “Last in — Fisrt Out” или “Последним вошел, первым вышел”.

Что означает декларируемый java принцип write once run anywhere. Смотреть фото Что означает декларируемый java принцип write once run anywhere. Смотреть картинку Что означает декларируемый java принцип write once run anywhere. Картинка про Что означает декларируемый java принцип write once run anywhere. Фото Что означает декларируемый java принцип write once run anywhere

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

Когда вызывается любой метод в Java, создается фрейм или область памяти в стеке, и метод кладется на его вершину. Когда метод завершает выполнение, он удаляется из памяти, тем самым освобождая память для следующих методов. Если память стека будет заполнена, Java бросит исключение java.lang.StackOverFlowError. К примеру, это может произойти, если у нас будет рекурсивная функция, которая будет вызывать сама себя и памяти в стеке не будет хватать.

Ключевые особенности стека:

Куча разбита на несколько более мелких частей, называемых поколениями:

Что означает декларируемый java принцип write once run anywhere. Смотреть фото Что означает декларируемый java принцип write once run anywhere. Смотреть картинку Что означает декларируемый java принцип write once run anywhere. Картинка про Что означает декларируемый java принцип write once run anywhere. Фото Что означает декларируемый java принцип write once run anywhere

Почему отказались от Permanent generation? В первую очередь, это из-за ошибки, которая была связана с переполнением области: так как Perm имел константный размер и не мог расширяться динамически, рано или поздно память заканчивалась, кидалась ошибка, и приложение падало.

Meta space же имеет динамический размер, и во время исполнения он может расширяться до размеров памяти JVM.

Ключевые особенности кучи:

Основываясь на информации выше, рассмотрим, как происходит управление памятью на простом примере:

У нас есть класс App, в котором единственный метод main состоит из:

— примитивной переменой id типа int со значением 23
— ссылочной переменной pName типа String со значением Jon
— ссылочной переменной p типа person

Что означает декларируемый java принцип write once run anywhere. Смотреть фото Что означает декларируемый java принцип write once run anywhere. Смотреть картинку Что означает декларируемый java принцип write once run anywhere. Картинка про Что означает декларируемый java принцип write once run anywhere. Фото Что означает декларируемый java принцип write once run anywhere

Как уже упоминалось, при вызове метода на вершине стека создаётся область памяти, в которой хранятся данные, необходимые этому методу для выполнения.
В нашем случае, это ссылка на класс person: сам объект хранится в куче, а в стеке хранится ссылка. Также в стек кладется ссылка на строку, а сама строка хранится в куче в String pool. Примитив хранится непосредственно в стеке.

Для вызова конструктора с параметрами Person (String) из метода main() в стеке, поверх предыдущего вызова main() создается в стеке отдельный фрейм, который хранит:

this — ссылка на текущий объект
— примитивное значение id
— ссылочную переменную personName, которая указывает на строку в String Pool.

После того, как мы вызвали конструктор, вызывается setPersonName(), после чего снова создается новый фрейм в стеке, где хранятся те же данные: ссылка на объект, ссылка на строку, значение переменной.

Таким образом, когда выполнится метод setter, фрейм пропадет, стек очистится. Далее выполняется конструктор, очищается фрейм, который был создан под конструктор, после чего метод main() завершает свою работу и тоже удаляется из стека.

Если будут вызваны другие методы, для них будут также созданы новые фреймы с контекстом этих конкретных методов.

8. Garbage collector

В куче работает Garbage collector — программа, работающая на виртуальной машине Java, которая избавляется от объектов, к которым невозможно получить доступ.

Разные JVM могут иметь различные алгоритмы сборки мусора, также существуют разные сборщики мусора.

Мы поговорим о самом простом сборщике Serial GC. Сборку мусора мы запрашиваем при помощи System.gc().

Что означает декларируемый java принцип write once run anywhere. Смотреть фото Что означает декларируемый java принцип write once run anywhere. Смотреть картинку Что означает декларируемый java принцип write once run anywhere. Картинка про Что означает декларируемый java принцип write once run anywhere. Фото Что означает декларируемый java принцип write once run anywhere

Как уже было упомянуто выше, куча разбита на 2 области: New generation и Old generation.

New generation (младшее поколение) включает в себя 3 региона: Eden, Survivor 0 и Survivor 1.

Old generation включает в себя регион Tenured.

Что происходит, когда мы создаем в Java объект?

В первую очередь объект попадает в Eden. Если мы создали уже много объектов и в Eden уже нет места, срабатывает сборщик мусора и освобождает память. Это, так называемая, малая сборка мусора — на первом проходе он очищает область Eden и кладёт “выжившие” объекты в регион Survivor 0. Таким образом регион Eden полностью высвобождается.

Если произошло так, что область Eden снова была заполнена, garbage collector начинает работу с областью Eden и областью Survivor 0, которая занята на данный момент. После очищения выжившие объекты попадут в другой регион — Survivor 1, а два остальных останутся чистыми. При последующей сборке мусора в качестве региона назначения опять будет выбран Survivor 0. Именно поэтому важно, чтобы один из регионов Survivor всегда был пустым.

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

Когда в Tenured места для новых объектов не хватает, происходит полная сборка мусора — Mark-Sweep-Compact.

Что означает декларируемый java принцип write once run anywhere. Смотреть фото Что означает декларируемый java принцип write once run anywhere. Смотреть картинку Что означает декларируемый java принцип write once run anywhere. Картинка про Что означает декларируемый java принцип write once run anywhere. Фото Что означает декларируемый java принцип write once run anywhere

Во время этого механизма определяется, какие объекты больше не используются, регион очищается от этих объектов, и область памяти Tenured дефрагментируется, т.е. последовательно заполняется нужными объектами.

Источник

Flutter: слоёный пирог с интересной начинкой. Графика

Что означает декларируемый java принцип write once run anywhere. Смотреть фото Что означает декларируемый java принцип write once run anywhere. Смотреть картинку Что означает декларируемый java принцип write once run anywhere. Картинка про Что означает декларируемый java принцип write once run anywhere. Фото Что означает декларируемый java принцип write once run anywhere

Write once, run anywhere

Заманчивая идея – написал код один раз, и он работает на всех платформах. По-моему, у Java это не плохо получилось. Дополнительная абстракция в виде байт-кода и JVM, отделяющая приложение от особенностей реализации платформы, помогла Java сделать своё дело.

В 1995 году, когда компания Sun провозгласила этот лозунг, ещё никто не знал что такое смартфон, а web-технологии только только начинали покорять мир. Похоже, с тех пор, многое изменилось. Количество IT-продуктов, как и их пользователей, росло огромными темпами, соответственно выросло количество технологий, инструментов и языков разработки. Акцент взаимодействия конечных пользователей с приложениями сместился в сторону web и мобильных платформ, а Android и iOS практически единолично поделили между собой мир мобильных устройств. Тем временем, можно определённо сказать, что лозунг «напиши один раз и запускай везде» приобрёл еще большую актуальность.

C точки зрения бизнеса, единая кодовая база, на которой можно собрать приложение с минимальными изменениями или дополнениями для различных платформ, звучит соблазнительно. Важную роль сегодня играет UI/UX, возможности для реализации которых, нам предоставляют web и мобильные платформы. И если, в плане мультиплатформенности бизнес-логики, к Java вопросов нет, то, например, про Swing думаю можно не обсуждать. Перед техническим погружением в реализацию механизмов отрисовки во Flutter, вкратце, опишу своё мнение о текущем состоянии мультиплатформы.

To Web or not to Web

Что означает декларируемый java принцип write once run anywhere. Смотреть фото Что означает декларируемый java принцип write once run anywhere. Смотреть картинку Что означает декларируемый java принцип write once run anywhere. Картинка про Что означает декларируемый java принцип write once run anywhere. Фото Что означает декларируемый java принцип write once run anywhere

Fresh start

Хорошая это была идея или плохая, покажет время. А пока, при упоминании Flutter, число классических мнений: «кладбище проектов google» и «зачем с нуля изобретать очередной велосипед» уменьшается пропорционально росту количества приложений на Flutter, вакансий и популярности проекта на GitHub, и социальной активности в общем, а появление SwiftUI и Jetpack Compose (и более экзотических) подтверждает жизнеспособность декларативного подхода при определении UI в коде.

Что означает декларируемый java принцип write once run anywhere. Смотреть фото Что означает декларируемый java принцип write once run anywhere. Смотреть картинку Что означает декларируемый java принцип write once run anywhere. Картинка про Что означает декларируемый java принцип write once run anywhere. Фото Что означает декларируемый java принцип write once run anywhere

Идея использования слоёв в IT-архитектуре, не нова, взять ту же Clean Architecture, которая позволяет нам разделить ответственности и взаимодействие между слоями. Flutter с самого начала своей истории активно использует этот подход. В первом приближении Flutter UI Toolkit делится на 3 слоя:

Что означает декларируемый java принцип write once run anywhere. Смотреть фото Что означает декларируемый java принцип write once run anywhere. Смотреть картинку Что означает декларируемый java принцип write once run anywhere. Картинка про Что означает декларируемый java принцип write once run anywhere. Фото Что означает декларируемый java принцип write once run anywhere

Framework

Это первый слой, с которым начинает «общаться» Flutter разработчик. А если быть более точным, и принять во внимание отличие понятий «библиотека» и «фреймворк», Flutter Framework, управляет написанным нами кодом. На языке Dart, создается декларативное описание интерфейса в виде древовидной компоновки объектов Widget, и уже сам фреймворк вызывает методы отрисовки или перестроения дерева виджетов.

Фреймворк также внутри разделен на слои, каждый со своей зоной ответственности.

Для исследования, возьмем простейший пример, состоящий из нескольких виджетов с простой конфигурацией.

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

После запуска приложения происходит инициализация так называемых Bindings, которые связывают фреймворк с нижним уровнем Engine.

SchedulerBinding Отвечает, в том числе, за обработку и формирование вызовов сигнализирующих о текущем статусе построения фрейма (BeginFrame, DrawFrame)

WidgetsBinding отвечает за перестроение дерева виджетов, построение elements и RenderObejct

RenderBinding После построения дерева элементов, RenderObject и их взаимосвязей, в работу включается слой фреймворка Rendering, который выполняет несколько этапов

Что означает декларируемый java принцип write once run anywhere. Смотреть фото Что означает декларируемый java принцип write once run anywhere. Смотреть картинку Что означает декларируемый java принцип write once run anywhere. Картинка про Что означает декларируемый java принцип write once run anywhere. Фото Что означает декларируемый java принцип write once run anywhereПодготовка сцены перед передачей на отрисовку в Engine

Flutter Engine

После того как сцена(Scene) со всеми командами отрисовки подготовлена, она передается на уровень Engine с помощью метода render. Затем из сцены извлекается LayerTree, производятся необходимые предварительные действия и проверка дерева. На данном этапе, работа в потоке UI завершается, а LayerTree передается на обработку в Raster поток.

Что означает декларируемый java принцип write once run anywhere. Смотреть фото Что означает декларируемый java принцип write once run anywhere. Смотреть картинку Что означает декларируемый java принцип write once run anywhere. Картинка про Что означает декларируемый java принцип write once run anywhere. Фото Что означает декларируемый java принцип write once run anywhere

Процессом непосредственной отрисовки на экран устройства управляет класс Rasterizer. Метод Draw этого класса запускается в отельном потоке Raster. Сначала в работу вступает композитор Flow, он разворачивает дерево и подготавливает слои дерева (LayerTree:Preroll) к отрисовке, а после выполняет команды отрисовки Skia, которые находятся в дереве (LayerTree:paint), замечу, в данном случае непосредственно отрисовки на экране не происходит, по сути собирается очередь из так называемых объектов операций Skia (см. addDrawOp)

Что означает декларируемый java принцип write once run anywhere. Смотреть фото Что означает декларируемый java принцип write once run anywhere. Смотреть картинку Что означает декларируемый java принцип write once run anywhere. Картинка про Что означает декларируемый java принцип write once run anywhere. Фото Что означает декларируемый java принцип write once run anywhere

В методе SkCanvas:Flush производится выполнение операций Skia, из очереди, которая была подготовлена на предыдущем этапе, эти операции выполняют непосредственную отрисовку в OpenGL буфер. После отрисовки вызывается метод платформы SwapBuffer, изображение появляется на экране, а цикл рендеринга фрейма в потоке GPU завершается.

Что означает декларируемый java принцип write once run anywhere. Смотреть фото Что означает декларируемый java принцип write once run anywhere. Смотреть картинку Что означает декларируемый java принцип write once run anywhere. Картинка про Что означает декларируемый java принцип write once run anywhere. Фото Что означает декларируемый java принцип write once run anywhere

Shaders

Ше́йдер (англ. shader «затеняющий») — компьютерная программа, предназначенная для исполнения процессорами видеокарты (GPU). Шейдеры составляются на одном из специализированных языков программирования и компилируются в инструкции для ЦП.

Существуют несколько вариантов языков описания шейдеров, в большинстве своём, это Си-подобные языки (Metal например использует спецификацию С++14). Чтобы абстрагироваться от разных вариантов языков, Skia, под капотом, использует свой формат SkSL, который фактически унаследован от OpenGL GLSL.

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

Вершинный и пиксельный шейдеры сгенерированые Skia для отрисовки квадрата

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

Что означает декларируемый java принцип write once run anywhere. Смотреть фото Что означает декларируемый java принцип write once run anywhere. Смотреть картинку Что означает декларируемый java принцип write once run anywhere. Картинка про Что означает декларируемый java принцип write once run anywhere. Фото Что означает декларируемый java принцип write once run anywhere

шейдеров гораздо больше (с учётом эффекта при нажатии кнопки)

Шейдеры классического примера с каунтером

Shader compilation jank

Поскольку шейдеры, по сути, просто программы на исходном языке, как и обычные программы на С, перед использованием на GPU их необходимо скомпилировать.

Здесь и проявляется проблема с пропуском кадров во время первых анимаций, которую сейчас горячо обсуждают в сообществе Flutter. По-умолчанию, в Skia, шейдеры компилируются перед использованием, если размер шейдеров небольшой, то это никак не влияет на поведение, а если, например, при анимации роута, на новом экране будут использоваться различные виды графических примитивов, которые потребуют значительное время на компиляцию шейдеров, то, в это время, текущая анимация может подлагивать.

Можно ли предварительно скомпилировать все возможные шейдеры, перед запуском программы?

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

Сам формат в котором Flutter сохраняет шейдеры закодирован с помощью base64, поэтому для удобства анализа я написал небольшую программу, которая может декодировать в читабельный вид. Ссылка на программу здесь. Плагин VSCode для подсветки синтаксиса здесь.

Metal

Выход metal и добровольно-принудительный переход на эту библиотеку в приложениях iOS, обострил проблему компиляции с новой силой. Дело в том, что предлагаемый метод «прогрева шейдеров», был реализован только на уровне OpenGL. Кроме того, текущий подход при компиляции шейдеров Metal MLSL, в некоторых случаях занимает больше времени, чем, при равных условиях, компиляция шейдеров OpenGL GLSL, что также повлияло на юзер экспириенс и справедливые возмущения разработчиков и бизнеса.

Подход к обработке скомпилированных объектов и их применении в пайплайне рендеринга Metal, немного отличаются от подхода в OpenGL, но, в любом случае методы предварительной компиляции описаны и доступны для использования. Также осенью прошлого года, Apple на WWDC2020 провела презентацию по использованию прекомпиляции и бинарных файлов при построении пайплайна GPU.

По моему мнению, эта проблема «первых кадров» лежит не в технической, а организационной плоскости, и команда Flutter не придавала должного значения анализу данной проблемы, а сама проблема решалась без привлечения специалистов по Metal. И только накал страстей и давление сообщества, помогло сдвинуть дело с мертвой точки, и последние недели на GitHub Skia, стали появляется изменения связанные с оптимизацией бинарных архивов Metal и подготовкой библиотек шейдеров.

Flutter For Web

Буквально пара слов про рендеринг на Canvas в вебе. Для рендеринга, HTML элемент сanvas, используется только для инициализации WebGL (по сути, калька с OpenGLES). Skia, как известно, хорошо работает с OpenGL. Поэтому фактически библиотека Skia написанная на C++, компилируется в WebAssembly с помощью Emscripten + добавляются некоторые байндинги и подключается к проекту.

Show must go on

Как видно Flutter пытается откусить достаточно жирный кусок у платформы, от неё, по-сути, требуется только поверхность для рисования, и некоторые системные вещи, и, сейчас, Flutter стабильно поддерживает Android/iOS/Linux/Windows/Web.

Конечно, такой кардинальный подход, который выбрала Flutter команда, не обходится без трудностей, но куда ж без них, без трудностей))

Источник

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *