что такое нативный код

Нативный код

Машинный код (также употребляются термины собственный код, или платформенно-ориентированный код, или родной код, или нативный код — от англ. native code ) — система команд (язык) конкретной вычислительной машины (машинный язык), который интерпретируется непосредственно микропроцессором или микропрограммами данной вычислительной машины.

Каждая модель процессора имеет свой собственный машинный язык, хотя во многих моделях эти наборы команд сильно перекрываются. Говорят, что процессор A совместим с процессором B, если процессор A полностью «понимает» машинный код процессора B. Если процессор A знает несколько команд, которых не понимает процессор B, то B несовместим с A.

«Слова» машинного языка называются машинными инструкциями. Каждая из них описывает элементарное действие, выполняемое процессором, такое как «переслать байт из памяти в регистр». Программа — это просто длинный список инструкций, выполняемых процессором. Раньше процессоры просто выполняли инструкции одну за другой, но новые суперскалярные процессоры способны выполнять несколько инструкций за раз. Прямой поток выполнения команд может быть изменён инструкцией перехода, которая переносит выполнение на инструкцию с заданным адресом. Инструкция перехода может быть условной, выполняющей переход только при соблюдении некоторого условия.

Также инструкции бывают постоянной длины (у MISC-архитектур) и диапазонной (у x86 команда имеет длину от 8 до 120 битов).

См также

Полезное

Смотреть что такое «Нативный код» в других словарях:

Исполняемый код — Эта статья о системе команд в целом; об инструкциях см.: Код операции (информатика). Машинный код (также употребляются термины собственный код, или платформенно ориентированный код, или родной код, или нативный код от англ. native code) система… … Википедия

Платформенно-ориентированный код — Эта статья о системе команд в целом; об инструкциях см.: Код операции (информатика). Машинный код (также употребляются термины собственный код, или платформенно ориентированный код, или родной код, или нативный код от англ. native code) система… … Википедия

Родной код — Эта статья о системе команд в целом; об инструкциях см.: Код операции (информатика). Машинный код (также употребляются термины собственный код, или платформенно ориентированный код, или родной код, или нативный код от англ. native code) система… … Википедия

Сравнение языков программирования — Эту статью следует викифицировать. Пожалуйста, оформите её согласно правилам оформления статей. Условные обозначения … Википедия

Интерпретируемый язык программирования — язык программирования, в котором исходный код программы не преобразовывается в машинный код для непосредственного выполнения центральным процессором (как в компилируемых языках), а исполняется с помощью специальной программы интерпретатора. В… … Википедия

Машинная инструкция — Эта статья о системе команд в целом; об инструкциях см.: Код операции (информатика). Машинный код (также употребляются термины собственный код, или платформенно ориентированный код, или родной код, или нативный код от англ. native code) система… … Википедия

Машинный язык — Эта статья о системе команд в целом; об инструкциях см.: Код операции (информатика). Машинный код (также употребляются термины собственный код, или платформенно ориентированный код, или родной код, или нативный код от англ. native code) система… … Википедия

Мобильная игра — Часть серии … Википедия

OCaml — Objective Caml Семантика: мультипарадигменный: функциональный, объектно ориентированный, императивный Автор(ы): INRIA Релиз: 4.00.1 (5 октября … Википедия

Источник

Что такое «Нативное приложение»?

JavaScript?! Как Phonegap? Не, я лучше сделаю нативное приложение.

Приложения на Titanium – это не сайты, которые чудесным образом обернуты в приложения.

Что ты имеешь в виду под «Нативной» разработкой?

А что делает приложение нативным?

Что такое хороший User Experience?

Выглядит и ведет себя ожидаемо

iOS, Android и Windows имеют различные требования к дизайну (iOS, Android,Windows) и если вы опираетесь на них, ваше приложение более предсказуемо и следовательно, проще в использовании.
Отличный пример – TabGroups. На Андроиде они, как правило, встроены в Action Bar и будут прокручиваться если их много. На iOS Tab Bar расположен внизу и если у вас больше пяти табов, то пятый будет вести на экран выбора нужного таба. На Windows Pivot Tabs работают почти как на Андроиде, но выглядят немного по-другому, они не являются частью Command Bar, который расположен внизу экрана.
что такое нативный код. Смотреть фото что такое нативный код. Смотреть картинку что такое нативный код. Картинка про что такое нативный код. Фото что такое нативный код
Так что технология, которая используется для разработки нативного приложения, не должна иметь собственные UI контролы, вместо этого она должна использовать те, которые предоставлены платформой.
В Titanium есть кросс-платформенные API почти для всего, и он всегда переводит их в платформенные UI-компоненты. Например, Ti.UI.TabGroup даст вам результат как на картинке выше, но напишете вы при этом один код (Alloy):

Для тех API, которые представлены не во всех платформах, мы используем пространства имен, например, Ti.UI.Android.CardView.

Единство API там, где это возможно, платформо-зависимые API – там, где нет. Всегда с уважением к целевой платформе.

Источник

Мобильная разработка: Cross-platform или Native

Всем привет! Я Игорь Веденеев, руководитель мобильной разработки в AGIMA. Поговорим немного о нативной и кроссплатформенной разработке. Раньше я по большей части скептически относился ко второй: не устраивало качество конечных приложений в первую очередь. Однако за последний год темпы развития кроссплатформенных фреймворков уже не в первый раз заставляют пересмотреть свое мнение насчет такого подхода. Поэтому давайте еще раз сравним самые популярные кроссплатформенные решения и нативную разработку.

что такое нативный код. Смотреть фото что такое нативный код. Смотреть картинку что такое нативный код. Картинка про что такое нативный код. Фото что такое нативный код

На всякий случай

Если вы не знаете, что такое нативная и кроссплатформенная разработка:

нативная разработка (2 независимых приложения на языках Swift и Kotlin);

кроссплатформенная разработка — общая кодовая база для iOS и Android (с применением фреймворков Flutter или React Native (далее RN)).

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

Нативная разработка

Нативная разработка — это классический способ создания приложения для iOS и Android. Ведется она с использованием инструментов и языков программирования, предложенных вендорами — Apple и Google. Языки в данном случае — Swift (iOS) и Kotlin (Android), а инструментов для профилирования и отладки в нативной разработке очень много.

Однако мы должны понимать, что в данном случае мы делаем два независимых приложения. Разрабатываются они параллельно. Каждое приложение может реализовать фичу по-своему, и у каждого могут быть свои баги. И самое главное, нативная разработка никуда не денется: пока существуют iOS и Android, Apple и Google будут предоставлять инструментарий для создания приложений.

Нативная разработка позволяет создать самое качественное и функциональное приложение, но взамен придется разрабатывать и отлаживать всё 2 раза и следить, чтобы приложения соответствовали друг другу функционально.

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

Плюсы и минусы нативной разработки

2 независимых приложения

Стоимость разработки и отладки

Меньше потребляемых ресурсов*

Богатый инструментарий для разработки

Широкий рынок разработчиков

Кроссплатформенная разработка

Кроссплатформенная разработка подразумевает, что мы используем один и тот же код и на iOS, и на Android. Вообще говоря, это всё такое же нативное приложение, но, запустив его, мы сразу проваливаемся в мир Flutter или RN, и всё происходит уже там. Стоит отметить, что разработка на Flutter/RN идет быстрее. Причем не только за счет того, что мы делаем 1 приложение вместо 2-х, а еще и за счет концепций создания приложений, в частности UI.

Но, увы, не всё так хорошо: кроссплатформа имеет ряд проблем, на которые стоит обратить внимание, прежде чем выбирать этот подход для своего приложения. React Native и Flutter всё же сторонние Open Source-решения. В них могут встречаться баги. Новые фишки iOS и Android там будут появляться не так быстро, как при нативных решениях. Может прекратиться поддержка, в конце концов.

Также, довольно часто придется полагаться на сторонние Open Source-библиотеки, что тоже несет в себе риски потенциальных проблем: например, совместимость версии Flutter/RN. Не исключен вариант, что нужной библиотеки не существует в природе, и тогда придется реализовывать всё с нуля самому. Также нельзя добавить расширения для iOS-приложений или, например, приложение на часы. Это касается и Flutter, и RN.

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

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

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

На картинке ниже представлены результаты теста с простым списком с изображениями: видим, что нативное приложение выигрывает вчистую. Да, на более новых моделях телефонов разница будет не такой значительной, но тенденцию можно видеть. Результаты остальных тестов тут.

что такое нативный код. Смотреть фото что такое нативный код. Смотреть картинку что такое нативный код. Картинка про что такое нативный код. Фото что такое нативный код

Если проще, то кроссплатформа позволяет разработать приложение в кратчайшие сроки. Лучше всего подходит для приложений-витрин услуг или товаров среднего/малого объема без обширного использования платформенных возможностей. То есть снять фотку на аватар или отсканировать QR-код не составит больших проблем, но, если вы делаете приложение вокруг камеры, лучше рассмотреть нативную разработку.

Плюсы и минусы кроссплатформенной разработки

Источник

Нативная разработка, React Native и Flutter: критерии выбора

Уже на стадии проектирования мобильного приложения важно понимать, какой язык выгоднее использовать для конкретного проекта. Наряду с нативной разработкой (например, для iOS — Swift или Objective-C, для Android – Java или Kotlin), используются кроссплатформенные фреймворки, такие как React Native и Flutter. Мы в SimbirSoft предлагаем несколько критериев, которые помогут в выборе как бизнесу, так и мобильному разработчику.

что такое нативный код. Смотреть фото что такое нативный код. Смотреть картинку что такое нативный код. Картинка про что такое нативный код. Фото что такое нативный код

Проблема выбора

В мире уже около пяти миллиардов смартфонов, по разным оценкам, до 80% из них используют операционную систему Android, и менее 20% – iOS. И все же в каждой стране есть свои особенности, так, в США более 65% смартфонов работают на iOS. При создании мобильных приложений чаще всего требуется выпустить версии как на iOS, так и на Android. Для этого можно обратиться к нативной или кроссплатформенной («гибридной») разработке.

Нативная разработка – это классическое решение, которое требует писать приложения под каждую платформу по отдельности, используя разные языки и учитывая особенности каждой платформы. При создании нескольких версий над проектом одновременно работают несколько команд.

Благодаря кроссплатформенным фреймворкам, появилась возможность «убить двух зайцев» разом и подготовить версии для iOS и Android с помощью одного инструмента. Среди фреймворков особенно широкое распространение получили:

— React Native от Facebook
для приложений iOS, Android и Windows
использует язык JavaScript и библиотеку React.js как основное средство разработки.

— Flutter от Google
для приложений Android, IOS и Fuchsia (подробнее см. нашу статью на Хабре)
использует язык Dart, который также служит для веб-программирования.

что такое нативный код. Смотреть фото что такое нативный код. Смотреть картинку что такое нативный код. Картинка про что такое нативный код. Фото что такое нативный код
Популярность React Native и Flutter растет, хоть и с разной скоростью, согласно статистике Google Trends.

Нативная разработка

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

Гибридная разработка

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

Критерии выбора Native, React Native и Flutter

Для бизнеса

1. Доступность

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

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

React Native и Flutter

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

Мы рекомендуем бизнесу нативные технологии, когда приложение рассчитано на продолжительную работу (иначе говоря, “срок жизни”). Также это выгодно при наличии потребности в высокой производительности, сложном интерфейсе и анимации, низком энергопотреблении, интеграции со сторонними ресурсами (API и др.). Нативные приложения более выгодны в перспективе за счет снижения затрат на техническую поддержку.

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

Памятка для бизнеса:

для сложных приложений – рекомендуем нативную разработку;
для простых приложений – гибридную.

2. Скорость + соответствие задаче

Время вывода на рынок (time-to-market) определяется, в первую очередь, размером доступной команды и особенностями мобильного приложения.

Работа с кроссплатформенными фреймворками может оказаться выгоднее и быстрее, если приложение простое, с одинаковым UI, без платформо-специфичных деталей, таких как доступ к камере, работа с файловой системой и отпечатками пальцев, runtime permissons. Здесь гибридная разработка позволяет сэкономить время за счет вторичного использования практически всего кода и UI под две платформы. Однако, при необходимости создания сложных кастомных view кроссплатформенная разработка замедляется.

Говоря о времени разработки мобильного приложения, важно понимать, что не существует “среднего срока по больнице”. Например, мы в своей практике выпустили банковское мобильное приложение за 100 дней, сейчас мы участвуем в дальнейшем развитии этого продукта. Вместе с тем были и простые приложения (срок запуска – около двух недель), и масштабные проекты со сроком разработки более года.

3. Безопасность и перспективность

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

В вопросе надежности нативная разработка опережает всех своих конкурентов. Развитие основных библиотек идет не один год, в них уже исправили большинство багов, нативные языки – такие, как Java, Objective-C, Swift, Kotlin – постоянно развиваются. Среди мобильных разработчиков можно услышать мнения, что в 2020-х годах нативную разработку на Android частично вытеснит Flutter, но пока это всего лишь предположение.

React Native предоставляет все инструменты для создания безопасных мобильных приложений, пример тому – Skype, Instagram, Facebook и другие известные продукты. Опасения за безопасность возможны только при использовании сторонних модулей при разработке. При этом JavaScript активно развивается, выпускаются новые фичи, в обозримом будущем риск устаревания минимален.

В случае разработки на Flutter риски выше, поскольку фреймворк молодой, релиз вышел только в декабре 2018 года. Пока что бывают проблемы, например, в тот или иной момент сборка библиотек доступна только под одну платформу, случаются сбои в Android Studio, есть баги в некоторых плагинах и библиотеках. С другой стороны, все это дорабатывают и исправляют. Нельзя исключать риск, что Google прекратит поддержку Flutter, как это уже было с другими проектами компании. Однако, на Flutter написана Fuchsia OS, в которой некоторые разработчики видят замену Android.

Для разработчика

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

— Уровень знания нативных языков и предпочтения команды

Каждая мобильная студия имеет свои предпочтения в выборе технологий. Нативная разработка требует максимально полного знания соответствующих языков. Однако, благодаря использованию нативных средств систем, меньше ограничений и сложности при кастомизации или осуществлении доступа к платформо-специфичным инструментам (в отличие от React Native и Flutter). При наличии опыта в JavaScript мобильный разработчик может довольно легко перейти на React Native (не нужно дополнительно изучать язык Dart, как в случае с Flutter) или на Dart (большим плюсом будет знание TypeScript).

React Native под капотом задействует нативные модули. Как следствие, если возникает потребность в кастомизации (и это не поддерживается из «коробки»), необходимо работать с модулями native. Например, в нашей практике был случай, когда приходилось кастомизировать библиотеку Яндекс.Карт для вывода кастомных визуальных составляющих на карте.

Flutter, в отличие от React Native, выделяется собственным графическим движком. С одной стороны, это позволяет при разработке простых приложений вообще не касаться native. С другой стороны, при необходимости обращения к native это означает дополнительные сложности (например, обмен сообщениями с элементарными типами данных и JSON) и невозможность использования графических компонентов native.

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

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

“Шпаргалка” для выбора

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

что такое нативный код. Смотреть фото что такое нативный код. Смотреть картинку что такое нативный код. Картинка про что такое нативный код. Фото что такое нативный код

Рекомендации

Если выбор сделан в пользу фреймворков, мы советуем обратить внимание на следующие аспекты работы:

Тестировать нужно все задействованные платформы (iOS, Android). Важно объективно оценить уровень знаний и опыт всех участников проекта, чтобы оценка в часах не оказалась заниженной. Предусмотрите риск появления багов в самих фреймворках React Native и Flutter во время разработки.

Некоторые элементы сложно (или вовсе невозможно) отрисовать в Flutter или React Native. По этой причине дизайн обязательно согласовать с разработчиками – причем до того, как заказчик влюбится в прекрасно отрисованную картинку.

На React Native не исключены специфические проблемы с автосборкой (например, из-за установки библиотек на разные платформы). Нужно заложить больше рискового резерва.

Реализация splash screen на Flutter происходит быстрее, чем на React Native, где этот элемент можно отрисовать лишь нативно, с большой вероятностью возникновения багов. При использовании React Native на splash screen со всеми отрисовками и багофиксами желательно заложить больше времени.

При использовании React Native верстку на iOS и Android нужно проводить одновременно, чтобы в дальнейшем избежать проблем при адаптации верстки под одну из систем.

Параллельная разработка web и mobile

Если веб-версия приложения написана на React, меньше расход времени на разработку мобильного приложения на React Native – за счет одинаковой логики компонентов.

Если приложение большое, на React Native проще провести тестирование и юнит тесты. На Flutter нужно закладывать больше времени на багофикс, поскольку логи не информативны.

Работа приложения с файлами системы

Нужно запрашивать разрешение к sd-card, при этом не с каждым файлом возможно получить имя и путь. Для отправки файла требуется использовать ContentResolver. Для того чтобы минимизировать риски, заложите время на все операции, связанные с файловой системой.

Доставка сборок клиенту

Здесь нет существенных отличий от нативной разработки, можно выбрать любой удобный сервис: Crashlytics, TestFairy, TestFlight.

React Native vs Flutter

Мы в SimbirSoft используем как React Native, так и Flutter, в зависимости от характера приложения. Делимся несколькими наблюдениями из нашей практики, которые помогают предусмотреть особенности работы с тем или иным фреймворком.

Источник

В нативный код из уютного мира Java: путешествие туда и обратно (часть 1)

что такое нативный код. Смотреть фото что такое нативный код. Смотреть картинку что такое нативный код. Картинка про что такое нативный код. Фото что такое нативный код

Java и другие управляемые языки просты и удобны во многих случаях, но иногда их возможностей недостаточно — например, если нужна библиотека, написанная только на C или C++. Иногда хочется позвать пару методов из системного API, или попытаться улучшить производительность для модуля — и тогда прямой путь в нативный код.

Но тут возникают подводные камни: написать нативный метод и вызвать библиотеку может быть и легко, но JVM начинает крашиться в случайных местах, производительность падает, сборщик мусора перестает справляться с работой, а в репозитории царствуют бесконечные C-шные файлы с буквами JNI. Что же могло пойти не так?

Иван Углянский (dbg_nsk) из Huawei разбирается со всем по порядку: что необычного в интеропе между Java и нативным кодом, как оно работало раньше и что нужно делать для их нормальной совместной работы (и можно ли это вообще сделать). Иван рассказывает, как избежать просадок производительности, внезапных OOM и размышляет на тему будущего — в контексте проектов Panama и Sulong.

Мы подготовили текстовую версию доклада о работе с нативами в Java. В первой части:

Во второй части подробнее расскажем, какие есть варианты, что из них быстрее и лучше, и есть ли универсальная библиотека — всё с примерами кода и подсказками.

Далее — повествование от лица спикера.

Сегодня мы говорим про нативный код, про путешествие из Java в него и обратно. Дело в том, что я JVM-инженер, 7.5 лет работал в Excelsior, где мы делали собственную виртуальную машину Excelsior JET, а вот уже чуть больше года работаю в компании Huawei, в команде Excelsior@Huawei, где мы продолжаем заниматься своим любимым делом: компиляторами, JVM и новыми языками программирования.

В результате я довольно много копаюсь во внутреннем устройстве JVM, смотрю, как это устроено, правлю — в том числе, и в реализации связки JVM с нативным кодом. Поэтому сегодня хочу вам про это рассказать.

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

Это означает, что реализацию этих методов стоит искать где-то ещё, например, в подгружаемых динамических библиотеках. И написана она может быть на каких-то других языках, например, на C/C++ или любом другом языке, где можно сделать C-like бинарные интерфейсы.

Бывают как простые сценарии, так и более сложные, что показывают уже методы на примере выше. Если вызываете первый метод goNative, то просто переходите из Java в C. А вот метод goThere позволяет перейти из Java в C, передать туда Java-объект callback и вызвать от него уже Java-метод.

что такое нативный код. Смотреть фото что такое нативный код. Смотреть картинку что такое нативный код. Картинка про что такое нативный код. Фото что такое нативный код

Таким образом, во время исполнения вашего приложения в call stack могут чередоваться java и нативные фреймы.

Зачем нам нужны нативы

Java — замечательный managed-язык, в котором очень много всего сделано для вашего удобства.

Там есть автоматическое управление памятью, и вы, наверное, уже отвыкли от проблем, типа утечек памяти, висячих ссылок и прочего — всё это осталось где-то в районе C, а в Java есть GC, который с этим хорошо справляется.

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

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

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

А вот нативный код — это его полная противоположность. Это Мордор, где шаг влево-вправо, и вас сжирает горный тролль.

Но знаете, иногда нужно выходить из уютного Шира и идти в путешествие к Роковой горе.

Кроме того, вы можете захотеть получить что-то напрямую от операционной системы. Допустим, вы хотите узнать, какой прокси стоит у вашего пользователя — напрямую из Java вы этого не сделаете, вам опять-таки нужно опуститься на уровень нативного кода и дёрнуть метод, например, из WinAPI в случае Windows.

Есть ещё одна мотивация. Многие люди привыкли думать, что Java тормозит, а вот C++ — это очень быстро. Поэтому если взять и переписать самый performance critical модуль проекта на плюсы, связать всё это через нативы, то получится огромное ускорение производительности. Почему эта мотивация довольно сомнительная, я покажу ниже, но в любом случае она присутствует.

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

И вот вы полны энтузиазма, написали своё приложение наполовину на С, наполовину на Java, запускаете, ожидаете, что сейчас всё ускорится, а в результате… получаете SIGSEGV, Exception_Access_Violation или ещё один SIGSEGV.

что такое нативный код. Смотреть фото что такое нативный код. Смотреть картинку что такое нативный код. Картинка про что такое нативный код. Фото что такое нативный код

В общем, ваше путешествие из Шира в Мордор заканчивается очень быстро, как у Боромира. Развал страшный, выглядит так, будто вообще сломалась сама виртуальная машина. Некоторые даже репортят баги, мол, JVM развалилась.

На самом деле чаще всего проблема в том, что они неправильно используют нативы.

В этом посте я в первую очередь хочу разобраться, почему так много проблем, почему люди получают SIGSEGV с нативами, во-вторых, показать вам безопасный путь, как можно пройти из Шира в Мордор, не отстрелить себе ногу, и не получить SIGSEGV, чтобы всё было безопасно и хорошо.

По ходу повествования мы будем все время сверяться вот с такой картой «Как позвать натив?»

что такое нативный код. Смотреть фото что такое нативный код. Смотреть картинку что такое нативный код. Картинка про что такое нативный код. Фото что такое нативный код

Если вы идете из Шира в Мордор, вам нужно ответить на три вопроса:

Ответы на эти вопросы подсветят нам самые больные места в механизме нативных вызовов и помогут избежать проблем.

История до нашей эры

Сначала чуть-чуть истории.

что такое нативный код. Смотреть фото что такое нативный код. Смотреть картинку что такое нативный код. Картинка про что такое нативный код. Фото что такое нативный код

Нативы можно было вызывать в Java ещё в самом начале, буквально в JDK 1.0 уже был Native Method Invocation, который позволял вызывать C-шные методы. Но он был заточен на детали реализации одной конкретной виртуальной машины, а именно на Sun JVM. На то, как там лежат объекты в памяти, какой сборщик мусора там используется.

Были и альтернативы. Например, Microsoft предлагала свой Raw Native Interface. Он был в чем-то лучше, в чем-то хуже, но тоже работал только с одной виртуальной машиной — теперь уже Microsoft J++.

Были попытки сделать нейтральные решения, как у Netscape, но в целом это были тёмные времена. Когда вы писали натив, вы не могли быть уверены, что это будет работать на всех JVM или хотя бы на каких-то.

Наша эра: JNI — Java Native Interface

Наша эра начинается с появления знаменитого Java Native Interface или JNI. Это был единый интерфейс, чтобы править всеми, и он был прекрасен, потому что был JVM нейтрален.

Он никак не затачивался на то, как сделана конкретная виртуальная машина, не важно, какая раскладка по объектам в памяти, неважно какой GC.

Если виртуальная машина поддерживает JNI, гарантируется, что ваш натив там заработает. Далее я буду говорить про JNI много плохого, но хочу акцентировать внимание: на тот момент это был огромный прогресс для всей отрасли, наконец-то мы могли писать нативы без страха, что они где-нибудь не заведутся.

Давайте посмотрим, как это работает.

Со стороны Java всё выглядит довольно мило, вы это уже видели.

Пишем методы без тела, пишем где искать реализацию, например, в System.LoadLibrary говорим подгрузить dll-ку, и после этого просто вызываем этим методы и переходим в С или С++.

Callback — это просто класс, у которого есть метод call, ничего не возвращающий, который печатает строку «Ok, we are in Shire again!», в моём случае мы вернулись в Шир на орлах.

что такое нативный код. Смотреть фото что такое нативный код. Смотреть картинку что такое нативный код. Картинка про что такое нативный код. Фото что такое нативный код

Как получить заголовку функций?

Теперь давайте попробуем написать нативную часть на языке С.

Здесь всё будет уже не так красиво, но нам нужно это сделать.

В результате мы получаем JavaToNative.h со всеми заголовками, но при этом то, что там написано, не очень-то похоже на нашу функцию.

Здесь появились какие-то заклинания типа JNICall. Здесь совсем другое имя метода: оно содержит еще и package и имя класса. И сигнатуры отличаются! У нас был 1 аргумент типа Callback, а здесь их уже три и они совсем другие.

что такое нативный код. Смотреть фото что такое нативный код. Смотреть картинку что такое нативный код. Картинка про что такое нативный код. Фото что такое нативный код

jclass появился, потому что натив был статическим и этим параметром передается Java-класс, чей статический метод вызывается. Callback превратился в jobject и появился новый JNIEnv со звёздочкой (про него чуть позже).

Правила, по которым генерируются заголовки, очень четкие и описаны в JNI-спецификации. Все примитивные типы превращаются в соответствующие примитивные C-шные (заданные макросами и базирующиеся на С-шных примитивных типах), все референс-типы превращаются в jobject или в редких исключениях в его наследников — jclass, jstring, jthrowable, jarray.

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

что такое нативный код. Смотреть фото что такое нативный код. Смотреть картинку что такое нативный код. Картинка про что такое нативный код. Фото что такое нативный код

Что за JNIEnv?

Аргумент JNIEnv * — это указатель на таблицу из 214 специальных функций, которая называется JNINativeInterface.

Вот некоторые из них:

что такое нативный код. Смотреть фото что такое нативный код. Смотреть картинку что такое нативный код. Картинка про что такое нативный код. Фото что такое нативный код

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

что такое нативный код. Смотреть фото что такое нативный код. Смотреть картинку что такое нативный код. Картинка про что такое нативный код. Фото что такое нативный код

JNINativeInterace помогает нам программировать на метауровне — как будто бы на Java, но используя мета-сущности: handle для классов, методов и так далее. Например здесь вы можете получить handle Java-класса, через него создавать его экземпляры (Java объекты), вызывать Java методы через специальные функции Call*Method, выбрасывать исключения.

Это очень похоже на рефлексию, только вы занимаетесь этим не в Java-коде, а в C.

Все эти функции JNI-интерфейса — единственный способ хоть как-то взаимодействовать с Java-миром: либо с объектами, либо просто получить информацию от виртуальной машины.

И это ответ на второй вопрос в нашей карте: как взаимодействовать с JVM. Вот так — через 214 функций, которые являются вратами в Шир.

Теперь давайте напишем нашей функции тело.

Для этого я получаю jclass, соответствующий классу моего аргумента, нахожу в нём метод, который называется call, возвращающий void, и вызываю этот метод с помощью JNI-функции CallVoidMethod. Должна напечататься строка, что мы вернулись на орлах и всё ок.

Как все это собрать?

Наконец, давайте обсудим, как все полученное ранее собрать.
Я использую Windows, поэтому гуглю заклинание, как собрать нативную библиотеку для JNI на этой системе:

что такое нативный код. Смотреть фото что такое нативный код. Смотреть картинку что такое нативный код. Картинка про что такое нативный код. Фото что такое нативный код

В результате у нас получается библиотека NativeLib.dll.

Это, конечно, довольно неприятно с точки зрения кроссплатформенности. Потому что, если вы собираете библиотеку для Linux или macOS — заклинания будут другими.

К счастью, есть замечательные тулы, которые позволяют от всего этого абстрагироваться. Например, Nokee plugins. Это кроссплатформенное решение, которое позволяет удобно добавить таргет в gradle скрипт и в результате собрать библиотеку под интересующие вас платформы.

Окей, тем или иным способом мы библиотеку собрали, после чего запускаем наше Java приложение, и получаем…

что такое нативный код. Смотреть фото что такое нативный код. Смотреть картинку что такое нативный код. Картинка про что такое нативный код. Фото что такое нативный код

Ура, мы только что совершили свое первое путешествие в Мордор и вернулись обратно. Теперь давайте поговорим, что же при этом может пойти не так. Кроме того, что нам пришлось пописать на не самом приятном языке C, да и выглядит это все довольно ужасно.

Что может пойти не так?

А пойти не так может очень много вещей…

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

Да, вы передавали объект callback, но он превратился в jobject, и какой был тип изначально — сходу не видно.

Допустим, у меня был бы какой-то другой аргумент, теперь уже java.lang.Object. И он бы тоже представлялся в нативном коде, как jobject, а потом я могу совершенно случайно по невнимательности позвать CallVoidMethod, передав туда в качестве аргумента не Callback, а какой-то java.lang.Object и попытаться из него позвать метод call (которого там, конечно, нет).

что такое нативный код. Смотреть фото что такое нативный код. Смотреть картинку что такое нативный код. Картинка про что такое нативный код. Фото что такое нативный код

Меня не остановит компилятор, не остановит runtime ровно до тех пор, пока не случится развал из-за попытки позвать call от java.lang.Object.

что такое нативный код. Смотреть фото что такое нативный код. Смотреть картинку что такое нативный код. Картинка про что такое нативный код. Фото что такое нативный код

Абсолютно похожая история с тем, какую конкретно JNI-функцию вы вызываете. Никто не проконтролирует, что вы используете именно СallVoidMethod, а не CallBooleanMethod или CallStaticVoidMethod или ещё что-то — это будет ваша ответственность. Если вы ошиблись, то случается неопределенное поведение (прям как в плохих программах на С), что начнет делать виртуальная машина — неизвестно.

Еще один момент, на который стоит обратить внимание: когда вы вызываете из натива Java-метод, он вполне может выбросить исключение, после чего исполнение возвращается в натив. В Java мы привыкли, что необработанное исключение автоматически пролетает дальше, ничего дополнительного делать не нужно. Но в данном случае это снова ваша ответственность! Вы должны проверить, а не случилось ли при вызове Java-метода исключения (с помощью функций ExceptionCheck или ExceptionOccurred), и если так, то обработать его здесь (с помощью ExceptionDescribe и ExceptionClear). Если же вы этого не сделаете, то в следующий раз, когда исполнение придет в Java-код, это исключение полетит уже совсем из другого неожиданного для вас места, и вы снова получите некорректное поведение.

что такое нативный код. Смотреть фото что такое нативный код. Смотреть картинку что такое нативный код. Картинка про что такое нативный код. Фото что такое нативный код

Вместо страшного и ужасного развала вы получите привычное исключение с понятным stacktrace, где будет написано, что вы перепутали MethodID или же используете не тот объект при вызове (что, собственно, у нас и происходит!).

что такое нативный код. Смотреть фото что такое нативный код. Смотреть картинку что такое нативный код. Картинка про что такое нативный код. Фото что такое нативный код

Это помогает быстро понять проблему и разобраться в большем проценте ошибок с нативами.

Это не означает, что будут вылечены все проблемы, но все самые простые — да.

Garbage Collector и Native-код

А теперь поговорим про последний пункт в нашей карте — как GC должен взаимодействовать с нативным кодом.

Почему про это вообще нужно говорить? Дело в том, что в Java коде, когда JVM нужно пособирать мусор, она приостанавливает Java потоки в специальных сгенерированных компилятором точках, которые называются GC safepoints. Давайте для простоты рассматривать случай StopTheWorld-коллекторов. В таком сценарии только после того, как все Java-потоки достигли ближайших safepoints и приостановились, начинают работать GC-треды, которые, собственно, собирают мусор.

что такое нативный код. Смотреть фото что такое нативный код. Смотреть картинку что такое нативный код. Картинка про что такое нативный код. Фото что такое нативный код

Это важно, потому что GC может двигать объекты во время своей работы. Для компактизации кучей, для своих каких-то целей — неважно. Если в этот момент кто-то из Java-тредов будет смотреть и взаимодействовать с Java хипом — читать или записывать поля некоторого Java объекта, то может случится неприятная ситуация: этот объект просто украдут у него из-под носа и перенесут в другую часть памяти. В результате вы получите некорректное поведение (например, развал).

Так вот проблема с safepoints в том, что в нативном коде такой фокус не пройдет.

Safepoints вставляют компиляторы из JVM, а если это какой-то внешний код, например на C или C++, скомпилированный clang-ом, то там нет никаких safepoint! В результате, мы просто не сможем остановить наши потоки, которые исполняют натив, чтобы пособирать мусор. Поэтому мы вынуждены смириться с тем, что нативы будут работать параллельно со сборкой мусора.

И тогда схема меняется так: появляются новые действующие лица, треды, исполняющие нативный код. Допустим, они ушли в натив до того, как нам потребовалось пособирать мусор, и вот они спокойно будут работать параллельно с GC-тредами.

что такое нативный код. Смотреть фото что такое нативный код. Смотреть картинку что такое нативный код. Картинка про что такое нативный код. Фото что такое нативный код

Есть ограничения. На входе в натив нам нужно сказать сборщику мусора: мы ушли в натив, не жди нас, спокойно собирай мусор. На выходе надо проверить, а не идет ли сейчас сборка мусора, и если идёт — приостановиться.

Но при этом всё ещё возникает проблема: даже в нативе вы не имеете права трогать Java-объекты, которые сейчас может взять и двигать GC.

Как вы помните, все наши Java-объекты в нативах почему-то превратились в jobject.

что такое нативный код. Смотреть фото что такое нативный код. Смотреть картинку что такое нативный код. Картинка про что такое нативный код. Фото что такое нативный код

Оказывается, что jobject — не просто маппинг для Java-ссылок, а специальные низкоуровневые хендлы, которые внутри инкапсулируют адрес на реальный Java-объект.

что такое нативный код. Смотреть фото что такое нативный код. Смотреть картинку что такое нативный код. Картинка про что такое нативный код. Фото что такое нативный код

Гарантируется, что Java-машина поддерживает связь этого адреса с реальным адресом объекта. То есть, если мы подвинули объект, то соответствующий jobject тоже будет пропатчен автоматически.

что такое нативный код. Смотреть фото что такое нативный код. Смотреть картинку что такое нативный код. Картинка про что такое нативный код. Фото что такое нативный код

С другой стороны, единственный способ повзаимодействовать с Java-миром из натива — это JNI-функции, которые также работают с jobject. Почти во всех из них стоит синхронизация с GC, так что вы не сможете сделать с объектами ничего плохого, пока идет сборка мусора.

что такое нативный код. Смотреть фото что такое нативный код. Смотреть картинку что такое нативный код. Картинка про что такое нативный код. Фото что такое нативный код

Если последним использованием ваших объектов была передача их в нативный код, то гарантируется, что за время исполнения этого натива их никто не соберет. Эти jobject являются своеобразными GC-root, что гарантирует выживание объекта.

Поговорим о том, какие проблемы это может вам доставить.

JNI References

Первая и главная проблема в том, что для хендлов реализована альтернативная система управления памятью. Это не похоже ни на Java, ни на C, скорее, что-то среднее между ними. Всё, что вы в коде видите, как jobject, на самом деле является сложным объектом JNI Reference, причем они бывают трех разных типов.

Во-первых, local references.

Они называются так, потому что они существуют не дольше, чем исполняется нативный метод, в котором был создан local reference (полная аналогия с локальными переменными).

Они интересны, во-первых, тем, что большинство JNI-reference — это именно LR. Передали какие-то Java-аргументы в натив — они автоматически заворачиваются в локалрефы, вызываете JNI-функцию, создающую объект — из нее тоже вернется локалреф. А во-вторых, с этими штуками, несмотря на, казалось бы, очень естественную и простую схему очистки, чрезвычайно легко получить утечку памяти.

Продемонстрирую это на небольшом примере:

Здесь мы будем аллоцировать в огромных количествах объекты прямо из нативного кода. Для этого находим соответствующий класс BornInNative с помощью JNI-функции FindClass, а получаем конструктор и метод-предикат, который будет говорить по соответствующему инстансу, нужно ли создавать следующий объект или нет. А потом просто в нативном коде с помощью JNI-функции NewObject начинаем эти объекты создавать.

что такое нативный код. Смотреть фото что такое нативный код. Смотреть картинку что такое нативный код. Картинка про что такое нативный код. Фото что такое нативный код

NewObject аллоцирует память, вызывает конструктор, который создает объект и возвращает в нативный код ту самую local reference, которую затем сохраняем в переменную obj типа jobject. От неё вызываем предикат, чтобы понять, нужно ли дальше аллоцировать объекты или нет.

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

На Java бы всё работало, но в нативном коде вам такого никто не гарантирует. Про Local reference гарантируется, что они умирают не позже, чем возврат из нативного метода. Но это и все: сами по себе от того, что вы переназначили переменную на другую LR, они умирать не обязаны и не будут.

что такое нативный код. Смотреть фото что такое нативный код. Смотреть картинку что такое нативный код. Картинка про что такое нативный код. Фото что такое нативный код

что такое нативный код. Смотреть фото что такое нативный код. Смотреть картинку что такое нативный код. Картинка про что такое нативный код. Фото что такое нативный код

Через несколько сотен миллионов итераций мы заметим, что аллокации стали фейлиться. JVM сейчас в коматозном состоянии, она пытается выкинуть out of memory, но ничего не получается, ведь в нативе мы это не обрабатываем. Обратите внимание на потребление памяти.

что такое нативный код. Смотреть фото что такое нативный код. Смотреть картинку что такое нативный код. Картинка про что такое нативный код. Фото что такое нативный код

Вы заказывали 1 ГБ, но потребление на самом деле уже 2 ГБ, потому что а) все Java-объекты удерживаются в heap, б) сами неумирающие jobject тоже занимают (нативную) память. В результате реальное потребление памяти вашим приложением превысило указанный лимит на дополнительный гигабайт.

Чтобы это починить, есть специальная функция DeleteLocalRef, которая говорит JVM, что локальная ссылка больше не нужна, ее можно уничтожить, а соответствующий объект собрать во время GC.

что такое нативный код. Смотреть фото что такое нативный код. Смотреть картинку что такое нативный код. Картинка про что такое нативный код. Фото что такое нативный код

Исправленная программа будет работать с любым разумным Xmx.

Так что с local Reference легко получить memory leak, но также легко получить и висящую ссылку. Попробуйте сохранить LR в static-поле, выйти из натива, вернуться и прочитать это поле. Получите некорректное значение.

Кроме LR есть другие хендлы, например Global Reference. Такие ссылки существуют до тех пор, пока вы явно их не освободите. Здесь ещё легче получить утечку памяти (достаточно просто забыть вызвать DeleteGlobalRef), но с другой стороны они более прямолинейны, нет неожиданностей. Забыли позвать DeleteGlobalRef — значит, будет утечка.

Наконец есть Weak Global Reference, это GR, но в них не гарантируется, что GC не соберет ваш объект. Это полная аналогия со слабыми ссылками из Java. Таким образом, все проблемы с ними актуальны и для нативов тоже.

что такое нативный код. Смотреть фото что такое нативный код. Смотреть картинку что такое нативный код. Картинка про что такое нативный код. Фото что такое нативный код

Еще больше сложностей с GC

Кроме проблем с JNI Reference стоит упомянуть, что у некоторых функций JNI-интерфейса есть очень интересные отношения со сборщиками мусора. Допустим, вы передаете в натив массив, он завернется в jobject, но получать доступ к каждому элементу по одному через jni-функции — это очень долго.

Вместо этого вы наверняка захотите получить доступ ко всему региону данных из массива за раз. Для этого есть специальные функции, например, GetIntArrayElements. Однако у нас опять есть проблема: мы не можем получить доступ к объекту, если в этот момент его может подвинуть GC. С этим нужно что-то сделать.

Есть две техники, как это можно реализовать. Во-первых, можно «запинить» объект, сказать сборщику мусора «давай мы не будем двигать пока массив, ты собирай мусор, а его не двигай».

Вторая тактика — просто скопировать его в нативную память, в нативе поработаем с копией, а потом обновим соответствующий массив.

JNI функции типа GetIntArrayElements даже поддерживают такую двойственность решения этой проблемы: у них есть третий аргумент — указатель на флажок. Если виртуальная машина решилась скопировать, то туда запишется true, если нет, то false, так что вы узнаете, что конкретно произошло.

Подводный камень здесь в том, что большинство виртуальных машин и сборщиков мусора не умеют pin-ать объекты по одному. Есть исключения, но скорее всего, как бы вы не надеялись на то, что копирования не случилось, оно произойдет. Так что при работе в нативе с массивом на 2 ГБ вы столкнетесь с копированием его в нативную память, что, конечно, может ударить и по производительности, и по общему потреблению памяти вашим приложением.

что такое нативный код. Смотреть фото что такое нативный код. Смотреть картинку что такое нативный код. Картинка про что такое нативный код. Фото что такое нативный код

Конечно, есть особенные JNI-функции типа GetArrayElementsCritical (и другие функции с суффиксом Critical), они всячески стараются не скопировать массив.

Пиннинга в большинстве GC нет, как они выходят из ситуации?

Они говорят: «Давайте на время исполнения этой функции вообще не будет сборки мусора, пусть GC подождёт». Это может сработать и дать хорошую производительность, вы поработаете без копий, но есть и обратная сторона медали.

Вы отодвигаете GC на неопределенный срок, что уже плохо само по себе, но при самом плохом сценарии вы можете просто получить дедлок и зависание вашего приложения. Подробнее про это можете почитать в посте Алексея Шипилёва.

Производительность нативных методов

И наконец, нельзя говорить про нативы и не обсудить их производительность. Раз вы вызываете C-код, то, конечно, кажется, что это должно чертовски быстро работать по сравнению с обычной Java. На самом деле — это большое заблуждение. Дело в том, что сам вызов нативных методов — это серьезная сложность для виртуальной машины. Давайте измерять!

Все замеры будем проводить на машине: Intel Core i7-7700 @ 3.60 GHz;16GB RAM, Linux Ubuntu 18.04

Начнем с простого примера. Мы из Java вызываем другой Java метод без параметров и обязательно без инлайна. Мерим это с помощью JMH, получаем 696 попугаев, (больше — лучше).

что такое нативный код. Смотреть фото что такое нативный код. Смотреть картинку что такое нативный код. Картинка про что такое нативный код. Фото что такое нативный код

Проведем другой эксперимент и вызовем из Java нативный метод, тоже пустой, без параметров и возвращаемого значения. И получаем просадку производительности в 3,3 раза на jdk8u252.

что такое нативный код. Смотреть фото что такое нативный код. Смотреть картинку что такое нативный код. Картинка про что такое нативный код. Фото что такое нативный код

При этом на jdk11 вы уже получаете просадку уже в 6 раз. Причины такой разницы в поведении разных версий Java рассмотрим в конце доклада, а сейчас продолжим наши измерения.

что такое нативный код. Смотреть фото что такое нативный код. Смотреть картинку что такое нативный код. Картинка про что такое нативный код. Фото что такое нативный код

Теперь давайте проведем более зловещий эксперимент и вызовем из Java натив, а оттуда через callback позовём пустой Java-метод. Логично предположить, что здесь случится проседание раза в два (ведь стало в два раза больше работы). На самом деле просадка будет в 10 раз.

что такое нативный код. Смотреть фото что такое нативный код. Смотреть картинку что такое нативный код. Картинка про что такое нативный код. Фото что такое нативный код

Т.е.возвращаться обратно из Java в натив дороже, чем просто уходить в натив.

Почему так происходит?

Если вы вызываете нативный метод, то, конечно, в сгенерированном коде хочется увидеть просто инструкцию call, вызывающую этот метод по какому-то адресу.

что такое нативный код. Смотреть фото что такое нативный код. Смотреть картинку что такое нативный код. Картинка про что такое нативный код. Фото что такое нативный код

И вы этот call получите, но вокруг него есть ещё некоторое количество работы для подготовки к вызову и обработки результата.

что такое нативный код. Смотреть фото что такое нативный код. Смотреть картинку что такое нативный код. Картинка про что такое нативный код. Фото что такое нативный код

Более конкретно кроме самого вызова нам нужно:

И всё это даёт просадку производительности в шесть раз.

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

Ну и про возвращение обратно в Java — так медленно работает из-за реализации конкретной виртуальной машины Hotspot. Когда вы делаете callback, происходит много лишней и тяжелой работы, в других виртуальных машинах результат мог бы быть гораздо лучше.

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

что такое нативный код. Смотреть фото что такое нативный код. Смотреть картинку что такое нативный код. Картинка про что такое нативный код. Фото что такое нативный код

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

В следующей части поговорим про сегодняшние альтернативы JNI, их сильные и слабые стороны, а также обсудим будущие проекты, которые вполне могут кардинально поменять все наше представление о нативах в Java: проекте Panama и Sulong.

Минутка нативной рекламы в тексте про нативный код. Раз вы здесь — похоже, вы Java-разработчик, который не боится покидать уютную хоббичью нору и покорять что-то новое для себя. В таком случае на конференции Joker (25-28 ноября, онлайн) наверняка будет интересное для вас — можете сами посмотреть программу на сайте.

Источник

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

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