Рубрики
Без рубрики

Java и собственный код в OpenJDK 13

Содержание Введение Практический Приложение libCurl Приложение libSSH2 Ссылки на Заключительные мысли приложения… Помеченный как java, ssh, программирование, с открытым исходным кодом.

  • Вступление
  • На практике
    • Приложение libCurl
    • Приложение libSSH2
  • Заключительные Мысли
  • Рекомендации

На прошлой неделе я наблюдал за довольно крутым выступлением НА конференции [1] с Микаэлем Видштедтом, директором по разработке программного обеспечения Oracle, где он представляет многие из предстоящих и разрабатываемых в настоящее время функций Java. Один из них, Проект Панама , показался мне особенно интересным.

Отказ от ответственности: Проект Панама все еще находится на ранних стадиях разработки, поэтому содержание этой статьи может не отражать его текущее состояние.

Project Panama, доступный в сборках JDK 13 с ранним доступом, предназначен для соединения Java и собственного кода. Чем это полезно? Существуют определенные случаи использования, когда часть функциональности доступна в виде библиотеки, написанной на C или C++, и требуется интегрировать ее в приложение Java. Текущее решение заключается в использовании собственного интерфейса Java (JNI) [2] что может потребовать огромного объема работы, а также довольно подвержено ошибкам. Вам нужно хорошо разбираться в внутренностях собственной библиотеки, а затем написать все необходимые реализации для соединения интерфейса Java с собственным кодом. По моему опыту, вызов встроенных библиотечных функций, которые могут измениться в какой-то более поздний момент времени, а также управление распределением памяти кучи может быть реальной проблемой с JNI. Процитировать Микаэля, как он говорит это на видео:

Сколько людей здесь написали JNI или, вы знаете, сделали ЭТО? Нам так жаль вас!

Вот тут-то и вступает в игру Панама. Он предоставляет новые инструменты и API для упрощения связи между Java и машинным кодом. В основном это сводится к следующим шагам:

  1. Создайте привязки Java (интерфейсы) из существующих заголовочных файлов C с помощью инструмента извлечь .
  2. Вызывайте функции C через извлеченный интерфейс Java с использованием java.foreign API.

Это позволяет вам сосредоточиться на написании основной логики вашего приложения, а не возиться с кодом клея и деталями интеграции.

Страницы документации проекта Панама [3] уже приведено солидное количество примеров для начала. Я просто бегло взгляну на то, как соединить и запустить libCurl Java-приложение а затем я хотел бы представить более подробный пример – простой SSH-клиент, который я написал на основе libSSH2 .

Я запускаю эти примеры на mac OS, но с помощью нескольких настроек вы также сможете запускать их на установке Linux.

Приложение libCurl

Как загрузить веб-страницу, используя реализацию собственной библиотеки Curl? Ну, сначала нам нужно достать и извлечь Панаму Сборка OpenJDK архив.

Давайте откроем оболочку и установим переменную среды JAVA_HOME в то место, где извлекается архив сборки OpenJDK.

export JAVA_HOME=/opt/jdk-13.jdk

Теперь нам нужно сгенерировать интерфейсы Java, код клея, который свяжет код Java с родной библиотекой. Это приведет к curl.jar файл:

$JAVA_HOME/bin/jextract -t org.unix -L /usr/lib -lcurl \
  --record-library-path /usr/include/curl/curl.h \
  -o curl.jar

Когда мы проверяем файл JAR, мы можем увидеть все вызовы API Curl, а также привязки зависимостей. API Curl доступен через новый java.foreign Java API.

Теперь для краткого примера. Вот фрагмент кода Java, который извлекает веб-страницу и отображает ее содержимое на экране.

import java.lang.invoke.*;
import java.foreign.*;
import java.foreign.memory.*;
import org.unix.curl.*;
import org.unix.curl_h;
import static org.unix.curl_h.*;
import static org.unix.easy_h.*;

public class Main {
   public static void main(String[] args) {
       try (Scope s = curl_h.scope().fork()) { 
           curl_global_init(CURL_GLOBAL_DEFAULT);
           Pointer curl = curl_easy_init();
           if(!curl.isNull()) {
               Pointer url = s.allocateCString(args[0]);
               curl_easy_setopt(curl, CURLOPT_URL, url);
               int res = curl_easy_perform(curl);
               if (res != CURLE_OK) {
                 System.err.println("Error fetching from: " + args[0] + " ERR: " + Pointer.toString(curl_easy_strerror(res)));
                 curl_easy_cleanup(curl);
               }
           }
           curl_global_cleanup();
       }
    }
}

Здесь следует отметить пару вещей. Обратите внимание, что мы не можем напрямую передать Java Строка для вызова curl_easy_setopt() . Этот вызов принимает указатель адреса памяти в качестве параметра url , поэтому сначала нам нужно выполнить операцию динамического выделения памяти с использованием Область действия и вместо этого передайте экземпляр интерфейса Указатель . Как вы можете найти в панамских технических документах [[5] , интерфейс Указатель очень помогает, когда дело доходит до сложных C-подобных операций с указателями, таких как арифметика указателей, приведения, разыменование памяти и т.д. Область управляет жизненным циклом динамической выделенной памяти во время выполнения.

Хорошо, теперь, вооружившись этими знаниями, можете ли вы расширить этот код, чтобы записать содержимое веб-страницы, извлеченной Curl, в поток файлов?

Приложение libSSH2

Вот более полный пример приложения, которое использует libSSH2 [4] для реализации простого SSH-клиента.

петров/ява-Панама-ssh2

Java SSH-клиент, использующий libssh2 через project Panama

Простой клиент Java SSH2, использующий собственную библиотеку libssh2 и проект JDK 13 .

записка: Это экспериментальный проект. Стабильность не гарантируется.

Устанавливать

Клиент был протестирован на macOS и Linux. Также должна быть возможность запустить его в Windows, однако в этом направлении не было проделано никакой работы. Пиарщики приветствуются!

Установите libssh2 .

  • macOS – заваривать установку libssh2
  • CentOS – yum установить libssh2.x86_64 libssh2-devel.x86_64

Получите последнюю версию Панамы Сборка JDK .

Откройте консольную оболочку и настройте JAVA_HOME var так, чтобы он указывал на JDK 13.

Создайте необходимые интерфейсы Java из собственных заголовков libssh2:

./gen_bindings.sh

Бежать

Для компиляции и запуска используйте:

./run.sh [-p|-k] hostname port username [path to ssh keys]
  • -p использует пароль для входа в систему. Вам будет предложено ввести свой пароль.
  • -k использует логин с открытым ключом. Вам нужно будет указать путь к вашим ключам, например, ~/.ssh .

Лицензия

Если вы хотите попробовать и настроить его для работы в Windows, я буду вам очень признателен.

Несколько моментов с моей стороны, которые я узнал или о которых думал во время работы с Панамой.

  • Область действия /довольно мощная. Вы можете выделять указатели обратного вызова, структуры, массивы. Концепция макетов и типов макетов заслуживает большего времени для моего полного изучения и понимания. Неудивительно, что написание кода Java с использованием собственной библиотеки является более обширным и требует особой осторожности, особенно когда дело доходит до того, чтобы не забывать вызывать вызовы API очистки, которые требуются библиотеке.
  • Для ввода-вывода в большинстве собственных библиотек требуется дескриптор файла, который нелегко получить в Java
  • [6] . Это, однако, не имеет прямого отношения к API java.foreign . Некоторые библиотеки определяют прототипы функций в стиле C++ без аргументов в отличие от типов аргументов в стиле C
  • Void . Иностранные документы [3] приведите пример этого случая при использовании API TensorFlow C. Я не исследовал, можно ли использовать Панаму с собственными библиотеками, созданными Go или Rust. Это было бы довольно круто.

Спасибо за чтение! 🍻

  1. GOTO 2019 • Проект Панамская часть
  2. Собственный интерфейс Java
  3. Панамские иностранные документы
  4. libSSH2 – библиотека C на стороне клиента, реализующая протокол SSH2
  5. Документы Панамского связующего v3
  6. Наиболее эффективный способ передачи дескриптора файла сокета Java в двоичный файл C

Оригинал: “https://dev.to/petarov/java-and-native-code-in-openjdk-13-18em”