uJVM: платформа для запуска Java-приложений на микроконтроллерах (MCU)

Моя цель - предложение широкого ассортимента товаров и услуг на постоянно высоком качестве обслуживания по самым выгодным ценам.

ИллюстрацияДобрый день, уважаемые хабровчане. В этом цикле статей я попытаюсь рассказать Вам о Java Virtual Machine и запуске Java программ на микроконтроллерах. Тема достаточно спорная: Зачем Java на микроконтроллерах, где и так мало ресурсов? Лучше нативного кода написаного на чистом С, ничего нет, даже на плюсах мало кто пишет! И т.д. Сразу скажу, сам задавал себе эти вопросы и не один раз. Мой ответ такой: Кто хочет попробовать, на что способно железо; понять, как работает JVM; увидеть интересный подход к построению мультиплатформенного проекта; внести свой вклад в Open Source; или просто побаловаться — все на борт, корабль по имени uJVM отправляется в плавание! Те кто уже настроился критиковать, смотрите как «Титаник» отправился в путь, надеюсь на Вашу лояльность!


Введение


Для затравки предлагаю Вам посмотреть видео ниже.


Если я правильно понял, то описанный в видео продукт состоит из OS, JVM и библиотек. Запускается он на многих контроллерах (можно посмотреть другие видео данной компании). Но решение оказалось закрытым, а мне захотелось попробовать поэкспериментировать. Я начал искать
альтернативу. И выбрал uJVM — исходники открыты, легко скомпилировать и запустить, можно принять участие в разработке.

В первой статье я кратко расскажу об архитектуре, процессе загрузки исходного кода, настройке окружения и получении первого результата: скомпилированные JVM и традиционное первое приложение HelloWorld.java, которые мы запустим на платформе x86_64. В последующих статьях перейдем к самому главному — запуску
uJVM на микроконтроллерах разных архитектур, портированию на новые платформы, добавлению новых Java и native классов. Итак, начнем.

uJVM


uJVM была разработана в соответствии с общей архитектурой, описанной в The Java Virtual Machine Specification Java SE 7 Edition и ее можно разделить на 3 части:

  • Class loader Загрузчик классов uJVM — может загружать содержимое классов, хранящихся в .class или .jar файлах в память, выполнять связывание и инициализацию.
  • Managed memory areas uJVM поддерживает потоки, хранение специальных регистров, выделение памяти для стеков, кучи и потоков.
  • Execution engine. Из-за жестких ограничений на объем памяти, в uJVM в качестве механизма выполнения используется только интерпретатор байт-кода — JIT-компилятор не реализован. Движок uJVM предоставляет доступ к коду Java, H/W драйверам (например, UART, GPIO и SysTick для большинства платформ) и нативным методам.

На данный момент uJVM доступна для следующих H/W платформ:

image

Тажке uJVM может быть легко портирована в качестве приложения под различные RTOS, например:

  • ZephyrOS
  • FreeRTOS
  • Nuttx

— но об этом я раскажу в другой серии статей.

uJVM — реализация JVM с открытым исходным кодом для встраиваемых систем с ограниченными ресурсами. Самая простая конфигурация требует ~6 KB RAM для исполнения и ~45 KB Flash ROM для хранения. Система сборки позволяет разработчику настраивать
uJVM, отключая ненужные функции для экономии ресурсов или включения поддержки определенных H/W-драйверов (например, использование FPU для ускорения вычислений с плавающей запятой и т.д.). Давайте посмотрим, как ее собрать и запустить…

Настройка окружения и загрузка исходного кода


1. Установка необходимых Linux пакетов


Для сборки uJVM я использую дистрибутив на основе Ubuntu 16.04, но Вы можете использовать любой другой дистрибутив Linux. Необходимо установить следующие пакеты:

$ sudo apt-get install git gcc make openjdk-8-jdk-headless gperf flex bison libncurses5-dev texinfo g++ curl pkg-config autoconf libtool libtool-bin libc6:i386 libc6-dev:i386 gcc-multilib doxygen doxygen-gui

2. Указание расположения компилятора Java (значение переменной JAVA_HOME)


Учтите, что папка, в которой находится компилятор Java (javac), должна быть известна системе сборки, для этого Вам следует (согласно инструкциям из документации Oracle Java) установить переменную окружения, указывающую на компилятор. В качестве альтернативы Вы можете использовать команду shell:

$ export JAVA_HOME = _java_compiler_directory_

В приведенной выше команде _java_compiler_directory_ не должен включать конечную папку bin; например, если компилятор находится в папке /usr/bin, в качестве значения JAVA_HOME должно быть указано /usr. Если Вы хотите навсегда присвоить это значение переменной JAVA_HOME для всех пользователей системы, Вы можете использовать следующую команду для добавления этой переменной в файл /etc/environment:

$ echo "JAVA_HOME=\"/usr\"" | sudo tee -a /etc/environment

Того же эффекта можно добиться, добавив переменную JAVA_HOME в файл /etc/profile с помощью следующей команды:

$ echo  "export JAVA_HOME=\"/usr\"" | sudo tee -a /etc/profile

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

3. Сборка kconfig-frontends под Linux (optional)


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

Обычно весь процесс сводится к скачиванию архива с исходным кодом, распаковке и запуску:

$ ./configure && make && sudo make install

3.1 Загрузка и распаковка исходного архива

$ curl -O http://ymorin.is-a-geek.org/download/kconfig-frontends/kconfig-frontends-3.12.0.0.tar.xz
$ tar -xf kconfig-frontends-3.12.0.0.tar.xz
$ cd kconfig-frontends-3.12.0.0

3.2 Патч

Если в вашей системе установлен gperf 3.0.4 или более ранней версии, Вы можете смело пропустить этот пункт.

gperf 3.1 (выпущен 5 января 2017 года) изменил тип, используемый в качестве аргумента длины в сгенерированных функциях, с unsigned int на size_t. Это приведет к сбою сборки со следующим сообщением об ошибке:

CC     libkconfig_parser_la-yconf.lo
    In file included from yconf.c:234:0:
    hconf.gperf:141:1: error: conflicting types for 'kconf_id_lookup'
    hconf.gperf:12:31: note: previous declaration of 'kconf_id_lookup' was here
     static const struct kconf_id *kconf_id_lookup(register const char *str, register unsigned int len);
                                   ^~~~~~~~~~~~~~~
    make[3]: *** [Makefile:456: libkconfig_parser_la-yconf.lo] Error 1
    make[2]: *** [Makefile:350: all] Error 2
    make[1]: *** [Makefile:334: all-recursive] Error 1
    make: *** [Makefile:385: all-recursive] Error 1

Процедура исправления ниже:

$ curl -O https://gist.githubusercontent.com/KamilSzczygiel/d16a5d88075939578f7bd8fadd0907aa/raw/1928495cfb6a6141365d545a23d66203222d28c0/kconfig-frontends.patch
$ patch -p1 -i kconfig-frontends.patch
$ autoreconf -fi

3.3 Настройка

Рекомендуемый набор опций для настройки kconfig-frontends:

$ ./configure --enable-conf --enable-mconf --disable-shared --enable-static

3.4 Компиляция и установка

$ make
$ sudo make install
$ sudo strip /usr/local/bin/kconfig-*

4. Клонирование репозитория uJVM


$ git clone https://github.com/Samsung/uJVM.git

Компиляция uJVM


Выберите PLATFORM x86_64_linux. После этого создайте контекст с параметрами конфигурации по умолчанию командой:

$ cd uJVM/
$ make PLATFORM=x86_64_linux create_context

Включаем приложение HelloWorld.java в сборку. Для этого запускаем конфигуратор:

$ make menuconfig

Переходим в меню приложений



и выбираем «Hello world example»



После этого HelloWorld.java будет включен в сборку

/**
 * @file		japps/hello_world/HelloWorld.java
 * @brief		Example how to use String and SysLog classes
 *
 * @copyright	Copyright (c) 2018 Samsung Electronics Co., Ltd. All Rights Reserved.
 * @author		Taras Drozdovskyi t.drozdovsky@samsung.com
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */

import ujvm.lang.*;

public class HelloWorld {
	public static void main() {

		SysLog.log("Hello world!\n");

		String hello = "Hello world!\n";
		SysLog.log(hello);

		byte[] bytes = { 'H', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd', '!', '\n' };
		String str = new String(bytes);
		SysLog.log(str);
	}
}

Пускай Вас не смущает SysLog.log(str) — это низкоуровневая функция вывода, аналог System.out.println(str). Стандартные билиотеки Java в uJVM пока еще не реализованы, но надеюсь это изменится — возможно, именно благодаря Вам!

Сохраняем и компилируем:

$ make

И наконец, запускаем!

$ make run



Можете дальше эксперементировать, подключая другие приложения!

В следующей статье начнем расмотрение запуска uJVM непосредственно под микроконтроллеры. Если руки зачесались, то Вы можете и сами начинать эксперементы, пользуясь инструкциями, которые можна найти в репозитории.
Источник: https://habr.com/ru/post/458772/


Интересные статьи

Интересные статьи

Я давно знаком с Битрикс24, ещё дольше с 1С-Битрикс и, конечно же, неоднократно имел дела с интернет-магазинами которые работают на нём. Да, конечно это дорого, долго, местами неуклюже...
Автор очень любит игру, и сам является администратором небольшого сервера «чисто для друзей». Как водится среди любителей, на сервере замодировано все, а это влечёт за собой нестабильность ра...
Введение Модель дисплея называется H016IT01. Данный дисплей интересен прежде всего тем, что он является транфлективным(transflective). Это означает, что изображение на нем должно быть видно даже...
Холмс: Любезнейший, не подскажите где мы находимся? Пастух: Вы находитесь на воздушном шаре!!! Холмс: Вы должно быть программист. Пастух: Да, но как вы догадались? Холмс: Только программист м...
Основанная в 1998 году компания «Битрикс» заявила о себе в 2001 году, запустив первый в России интернет-магазин программного обеспечения Softkey.ru.