Java und OSGi in Embedded-Systemen für das Internet der Dinge

Optimierte Java Virtual Machines (JVMs) und moderne, kostengünstige Hardware ermöglichen den Einsatz von Java auch im Embedded-Bereich. OSGi, das dynamische Modulsystem für Java, liefert zusätzlich die noch fehlenden Puzzlestücke, um ein modernes, flexibles, sicheres und (fern-)wartbares System zu entwickeln.

In Pocket speichern vorlesen Druckansicht 1 Kommentar lesen
Lesezeit: 16 Min.
Von
  • Kai Hackbarth
  • Konstantin Kersten
Inhaltsverzeichnis

Das OSGi-Schichtenmodell (Abb. 1)

Optimierte Java Virtual Machines (JVMs) und moderne, kostengünstige Hardware ermöglichen den Einsatz von Java auch im Embedded-Bereich. OSGi, das dynamische Modulsystem für Java, liefert zusätzlich die noch fehlenden Puzzlestücke, um ein modernes, flexibles, sicheres und (fern-)wartbares System zu entwickeln.

Von den ersten Einsätzen im "Project Green" bis heute hat Java einen langen Weg hinter sich gebracht. Das gilt insbesondere bei eingebetteten Systemen, die in der Vergangenheit oft hardwarebedingt nicht leistungsfähig genug waren, um Java ausführen zu können. Um zu verstehen, warum Java trotzdem eine prominente Rolle im Embedded-Markt spielt und warum es zunehmend relevanter wird, lohnt sich ein tiefergehender Blick.

"Write once, run anywhere" ist der Leitsatz, der viele Vorteile von Java zusammenfasst. Denn im besten Fall schreiben Entwickler ihre Applikation nur ein einziges Mal. Da es für viele verschiedene Plattformen eine JVM gibt, kann man die Applikation überall dort laufen lassen, wo eine solche installiert ist. Das führt automatisch dazu, dass ein Entwickler auf eine Vielzahl von Java-Standardbibliotheken zugreifen kann und nicht jedes Mal das Rad neu erfinden muss. Die Wiederverwendung von Code wird dadurch stark gefördert und Interoperabilität vereinfacht.

Es existiert ein sehr großes Ökosystem, das durch eine große und aktive Community vorangetrieben wird. Sie besteht aus vielen Java-Entwicklern, aber auch aus unterstützenden Unternehmen und Organisationen. Über den sogenannten Java Community Process (JCP) besteht die Möglichkeit, Änderungen und Erweiterungen der Java-Programmiersprache voranzutreiben und so neue standardisierte technische Spezifikationen zu erstellen. Diese werden als Java Specification Requests (JSRs) bezeichnet.

Im Laufe der Zeit hat die Community einen Fundus an Werkzeuge bereitgestellt. Dazu gehören zum Beispiel die mächtigen Entwicklungsumgebungen Eclipse, IntelliJ IDEA oder NetBeans, aber auch kleinere Tools wie JavaDoc, Jedit und JUnit. Letzteres beispielsweise ermöglicht es, schnell und einfach Unit-Tests durchzuführen. JavaDoc kann bei der wichtigen, aber auch unliebsamen Aufgabe des Dokumentierens unterstützen.

Des Weiteren kann man auf Build-Management-Werkzeuge wie Ant oder Maven zurückgreifen, und in Zeiten von Continuous Integration können Werkzeuge wie Hudson und Jenkins von großem Wert sein, da sie die Wartbarkeit des Codes verbessern.

Auch die Sprache selbst ist zu betrachten. Java nutzt beispielsweise Exceptions, um mit Fehlern und außergewöhnlichen Events umzugehen, es ist objektorientiert und robust. Mit dem Garbage Collector lassen sich größere Programmierfehler vermeiden, was zu einer gesteigerten Systemstabilität beiträgt. Man kann eine Softwarekomponente auf dem PC mit den gleichen Werkzeugen entwickeln und testen, egal ob es sich um ein Enterprise-, Desktop-, oder Embedded-System mit Echtzeitanforderungen handelt. Das hilft Unternehmen, ihre Entwickler flexibel einzusetzen. Dazu kommt, dass Java im Vergleich zu vielen anderen Programmiersprachen relativ schnell zu erlernen ist.

Man sieht an dieser Auswahl, warum es Sinn macht, darüber nachzudenken, Java bei eingebetteten Systemen einzusetzen. Es existieren ein gutes Ökosystem, viele Werkzeuge, eine objektorientierte, schnell zu erlernende Sprache, und man ist weitgehend unabhängig von der verwendeten Hardware.

Wenn die meisten an die Java-Programmiersprache denken, meinen sie Oracles Java Standard Edition. Die Java SE stellt die Kernfunktionen der Programmiersprache bereit. Sie definiert alles, von den Grundtypen und Objekten der Sprache bis hin zu den komplexen Klassen, die für Netzwerk, Sicherheit, Datenbankzugriff, GUI-Entwicklung und XML-Parsing benötigt werden. Zusätzlich zu den Kernklassen besteht die Java-SE-Plattform aus einer virtuellen Maschine, Entwicklungstools, Deployment-Techniken und anderen häufig in Java-Applikationen verwendeten Klassenbibliotheken und Toolkits.

Für den Enterprise-Bereich wurde die Java Enterprise Edition als Erweiterung der Java-SE-Plattform geschaffen. Java EE stellt weitere Klassen zur Verfügung, um groß angelegte, verteilte und skalierbare Systeme zu entwickeln. Im Gegensatz dazu steht die Java Micro Edition. Java ME verfügt über eine API und eine "leichtgewichtige" virtuelle Maschine, um Java auf "limitierten" Geräten wie Mobiltelefonen laufen zu lassen. Sie wurde ursprünglich eingeführt, um den Einschränkungen kleiner Geräte, also Geräten mit begrenzter Leistung, Speicher, Display und Stromverbrauch Rechnung zu tragen.

Java-ME-Konfigurationen sollen eine breite Klasse von unterstützten Geräten abdecken. Die Java Connected Limited Device Configuration (CLDC) wurde für Kleinstgeräte wie Pager definiert und kam auch häufig in Feature Phones zum Einsatz. Das dynamische Laden von Klassen wird hier beispielsweise nicht unterstützt. Auch fehlen essenzielle Klassen, die gerade der Sektor M2M (Machine-to-Machine) benötigt. Das sind beispielsweise die java.io- und java.net-Klassen, die teilweise komplett fehlen oder nur durch Erweiterungen verfügbar sind.

Die Java Connected Device Configuration (CDC) ist im Gegensatz dazu für mittelgroße Embedded-Geräte wie Blu-ray Disc Player, VOIP-Telefone, Fernsehgeräte, Set-Top-Boxen, Drucker oder Residential Gateways gedacht. Profile unter gliedern dann die Konfigurationen weiter. Das Foundation Profile ist ein gutes Beispiel dafür. Es erfüllt unter anderem Anforderungen, die für Geräte gedacht sind, die beispielsweise kein grafisches Interface benötigen.

Mit der zunehmenden Bedeutung von Java im Embedded-Bereich hat Oracle nun das Produktportfolio überarbeitet und macht Java ME und Java SE für den Embedded-Markt fit. Ausgehend von der Java SE ist das neue Java SE Embedded entstanden, das sich auf Systemen mit jeweils mindestens 32 MByte RAM und Flash-Speicher nutzen lässt. Neue, sogenannte "Compact Profiles" erlauben es, Subsets der Standard Edition zu erzeugen.

Für weniger leistungsfähige Systeme ist Java ME Embedded 8 gedacht, das kompatibel zu Java SE ist und sich schon ab 8 MByte RAM nutzen lässt. Es basiert auf Java ME CLDC 8 und dem Java ME Embedded Profile (MEEP) 8

1999 wurde die OSGi Alliance (damals Open Services Gateway Initiative) gegründet, mit dem Ziel, die stetig wachsende Komplexität und stärkere Vernetzung von Systemen in den Griff zu bekommen. Die 15 Gründungsmitglieder, darunter Alcatel, Ericsson, IBM, Motorola, Oracle, Philips, Sun Microsystems und Toshiba, fokussierten sich zunächst auf die Spezifikation eines Java-Komponentensystems für sogenannte Service Gateways zur Realisierung des intelligenten Heims.

Das OSGi Framework ist das Kernelement der Spezifikationen. Es dient als Laufzeitumgebung für Softwarekomponenten und orientiert sich stark an den Prinzipien der serviceorientierten Architektur (SOA). Das Framework lässt sich gut mit den folgenden Eigenschaften beschreiben: modular, offen, dynamisch und erweiterbar.

Das OSGi-Schichtenmodell (Abb. 1)

Wie in Abbildung 2 dargestellt, ist das OSGi Framework in mehrere Schichten aufgeteilt. In der Modulschicht wird das Format der Module definiert, in OSGi-Terminologie werden sie als Bundles bezeichnet. OSGi Bundles setzen sich aus Java-Klassen und anderen Ressourcen (z. B. HTML-Dateien und Bilder) zusammen. Es ist möglich, mehrere Bundles gleichzeitig in einem JVM-Prozess ausführen zu lassen. Bundles können sich Packages untereinander zur Verfügung stellen, diese bei Bedarf aber auch voreinander verstecken. Jedes Bundle verfügt über eine Manifest-Datei, die zusätzliche Metainformationen bereitstellt. Das bedeutet Informationen wie Bundle-Name, -Version und -Hersteller, aber auch Abhängigkeiten zu anderen Bundles via Import und Export.

Über den Lifecycle Management Layer lässt sich der Lebenszyklus von Bundles kontrollieren. Diese können beispielsweise über eine lokale Konsole oder über ein Management-System aus der Ferne installiert, gestartet, gestoppt und deinstalliert werden. Das Bundle bekommt bei der Installation einen eindeutigen Identifier zugeordnet. Sofern Abhängigkeiten zu anderen Bundles bestehen sollten, sind diese zunächst aufzulösen, bevor ein Bundle gestartet werden kann. Somit lassen sich unerwünschte Nebeneffekte, zum Beispiel unerklärliche Abstürze, vermeiden.

Der Service Layer führt das Programmiermodell der serviceorientierten Architektur nach dem "Publish-Find-Bind"-Modell ein. Ein OSGi-Service wird in Form eines Java-Objekts repräsentiert, das sich über eine Java-Schnittstelle bei der OSGi Service Registry an- beziehungsweise abmelden kann. Die OSGi Service Registry fungiert als Bindeglied, wobei hier die Laufzeitdynamik zu beachten ist, da Bundles jederzeit kommen und gehen können.

Mit standardisierten OSGi-Mechanismen, zum Beispiel dem ServiceTracker, kann der Bundle-Lifecycle überwacht werden. Die Sicherheitsschicht ist optional und setzt auf der Java-2-Sicherheitsarchitektur auf, um mit digitalen Signaturen den Ursprung von Softwarekomponenten authentifizieren zu können.

Im Mai 2000 wurde die erste Spezifikation der OSGi Alliance veröffentlicht. Es wurden zunächst nur das eigentliche Framework und Dienste zur Geräteverwaltung für Home Gateways, Set-Top-Boxen und DSL-Modems spezifiziert. Seitdem kamen zahlreiche weitere Spezifikationen hinzu. Derzeit wird am sechsten Release gearbeitet, das Neuerungen für die Entwicklung von Enterprise-/Cloud-Anwendungen, aber auch für Home Gateways enthalten wird.

Im August 2013 wurde der Entwicklungsprozess der OSGi Alliance erneuert, der es nun der Entwickler-Community ermöglicht, die Spezifikationsarbeiten zu verfolgen und zu kommentieren. Hierzu wurde ein GitHub-Repository eingerichtet, in dem die aktuellen Dokumente zur Verfügung stehen.

Der Kern der OSGi-Spezifikation wurde stetig so generisch gehalten, dass er in nahezu allen Umgebungen zum Einsatz kommen kann. Bei eingebetteten Systemen hat sich OSGi als Standard für modulare Softwarearchitekturen in Home-Gateways durchgesetzt. Darüber hinaus ist die Eclipse-Entwicklungsumgebung sicherlich eines der bekanntesten Beispiele für den Einsatz von OSGi. Mittlerweile basieren außerdem nahezu alle Java-Enterprise-Applikationsserver auf OSGi (darunter WebSphere, JBoss, WebLogic und NetWeaver).

Die Bereiche Gesundheit, Energie, Fahrzeugtelematik, Transport und Logistik, aber auch die industrielle Automatisierung (Industrie 4.0) verändern sich derzeit aufgrund der Entwicklung bei M2M beziehungsweise dem Internet der Dinge grundlegend. OSGi wurde hier als eine der Kerntechniken identifiziert, wie eine Umfrage von Bosch Software Innovations im Mai 2013 zeigte. OSGi war hier mit 46 Prozent die wichtigste Technik für das Internet der Dinge.

Aufgrund vieler Vorteile werden heute nahezu alle komplexen Softwaresysteme modularisiert. Im Vordergrund stehen die Time-to-Market und die Reduzierung der Entwicklungskosten durch größtmögliche Wiederverwendung von Softwarekomponenten. Bei serviceorientierten Architekturen haben Studien gezeigt, dass die Wiederverwendung von Softwarekomponenten kurzfristig zu Einsparungen von 5 bis 10 Prozent führen kann und über einen längeren Zeitraum sogar bis zu über 40 Prozent.

Durch die daraus resultierende Komplexitätsreduktion lassen sich Projektrisiken minimieren, während gleichzeitig die Qualität steigt. Bei eingebetteten Systemen lassen sich mit Java und OSGi noch höhere Einsparungen erreichen, da hier eine Vielzahl unterschiedlicher Prozessoren und Betriebssysteme zum Einsatz kommen.

OSGi existiert bereits seit 15 Jahren und hat sich in vielen Umgebungen bewährt. Es gibt derzeit kein weiteres standardisiertes Modulsystem für Java. Oracle beziehungsweise Sun haben mit dem Projekt Jigsaw versucht, einen eigenen Weg zur Modularisierung für Java zu finden. Die Java- und OSGi-Community zeigte sich von dieser Entwicklung allerdings bis dato nur wenig begeistert. Nach mehreren gescheiterten Versuchen wurde im letzten Jahr entschieden, dass das Projekt Jigsaw nicht vor Java 9, also vermutlich nach 2015, eingeführt wird.

Fragt man vor diesem Hintergrund Entwickler, warum sie Java noch nicht im Embedded-Umfeld einsetzen, sind in der Regel folgende Argumente zu hören: Java sei für den Einsatz in eingebetteten Systemen viel zu hardwarefern, zu langsam, zu groß und nicht echtzeitfähig. Es ist richtig, dass in Java geschriebene Programme in maschinenunabhängigen Bytecode kompiliert werden. Diesen muss dann ein Interpreter auf der jeweiligen Hardware interpretieren. Dadurch ist jedoch nur der Interpreter, die JVM, auf die jeweilige Hardwarearchitektur anzupassen und zu kompilieren.

Die frühen Interpreter waren noch recht groß und nicht optimal auf die Hardware angepasst. Das hat sich durch heutige JVMs mittlerweile grundlegend geändert. Dass diese Entwicklung nicht neu ist, zeigt ein 2010 veröffentlichtes Whitepaper des Kölner Unternehmens ProSyst. Es verdeutlicht, dass Java in Kombination mit OSGi auch auf kleinen Hardwareplattformen (ARM9 mit 156 MHz und 8 MByte RAM und Flash-Speicher), in diesem Fall im Automotive-Bereich, nutzbar ist und dabei noch genug Platz für Apps und Services "übrig lässt".

Auch an der Schnelligkeit von Java hat sich durch die modernen Interpreter einiges verbessert. Um die Ausführungsgeschwindigkeit zu erhöhen, werden Konzepte wie die Just-in-time-Kompilierung (JIT) und die Hotspot-Optimierung verwendet. In Bezug auf den eigentlichen Ausführungsvorgang kann die JVM den Bytecode also interpretieren, ihn bei Bedarf jedoch auch kompilieren und optimieren. Heute verfügt Java durch das Java Native Interface (JNI) über eine standardisierte Funktionen aufzurufen. Wird JNI genutzt, benötigt man auf allen Plattformen, auf der das Java-Programm laufen soll, allerdings die native Programmbibliothek.

Java unterstützt wie die meisten der Betriebssysteme, auf denen es läuft, kein striktes, auf Prioritäten basierendes Threading-Modell. Dazu kommt, dass der in Java vorhandene Garbage Collector Unterbrechungen bei der Ausführung von Berechnungen bewirken kann. Aufgrund dessen wurde schon früh die Java-Real-Time-Spezifikation geschaffen. Dort wird zusätzlich zu einem Threading-Modell eine Sektion im Speicher eingeführt, die nicht unter die Kontrolle des Garbage Collector fällt. Diese Real-Time-Java-Systeme kommen beispielsweise im Banken- und Militärbereich zum Einsatz.

Der Embedded Markt wächst rasant. Das Internet der Dinge und die M2M-Kommunikation treiben die Anzahl der Embedded-Geräte in die Höhe. Cisco erwartet, dass 2015 25 Milliarden Geräte beziehungsweise "Dinge" mit dem Internet verbunden sein werden und sich diese Zahl bis 2020 auf 50ˇMilliarden erhöhen wird. Diese Geräte werden nicht nur zunehmend mehr, sondern auch performanter. Moores Gesetz besagt, dass sich die Komplexität integrierter Schaltkreise mit minimalen Komponentenkosten regelmäßig verdoppelt. Das führt dazu, dass Java auf immer mehr Geräten lauffähig ist.

Der kreditkartengroße Einplatinenrechner Raspberry Pi ist bestückt mit einem 700-MHz-ARM-Prozessor sowie 512 MByte Arbeitsspeicher. Ihn gibt es schon ab circa 30 Euro zu kaufen, aber es handelt sich trotzdem um einen vollwertigen kleinen PC. Klassische M2M-Plattformen sind sogar noch kleiner und ermöglichen es trotzdem, Java zu nutzen.

Gerade die rasante Entwicklung im Internet der Dinge führt dazu, dass Unternehmen schneller komplexe Anwendungen auf den Markt bringen müssen. Die Nutzung standardisierter Softwaremodule mit ausgereiften und optimierten Werkzeugen wird somit zunehmend wichtiger. Java in Kombination mit OSGi bietet hier einen enormen Vorteil für den Einsatz in der neuen Generation eingebetteter Systeme.

Konstantin Kersten
erarbeitet bei der ProSyst Software GmbH als Projektmanager auf Java- und OSGi-basierende Lösungen für Kunden im IoT/M2M-Bereich.

Kai Hackbarth
ist seit 13 Jahren bei der ProSyst Software GmbH beschäftigt. Darüber hinaus leitet er das OSGi Requirements Committee und ist Co-chair der Residential Expert Group.

  • Gerd Wütherich, Nils Hartmann, Bernd Kolb, Matthias Lübken; Die OSGi Service Platform – eine Einführung mit Eclipse Equinox; dpunkt.verlag 2008

Die Beispielarchitektur unten zeigt, wie man einfach eine Abstraktion von Geräten mit Java und OSGi auf dem Raspberry Pi realisieren kann. Im ersten Schritt erfolgt die Installation eines Betriebssystems für Raspberry Pi (z. B. Raspbian), im zweiten ist Java auf dem Raspberry Pi zu installieren (entfällt bei den neuen Raspbian-Builds, da Java schon integriert ist):

sudo apt-get update && sudo apt-get install oracle-java7-jdk

Schließlich muss man noch OSGi installieren. Hier wird der mBS Smart Home Stack von ProSyst genutzt. Er enthält die genannte Hardwareabstraktionsebene. In diesem Beispiel werden ZigBee, Z-Wave und Bluetooth genutzt, um Sensoren und Aktoren über die jeweiligen Protokoll-USB-Controller und dem USB2Serial-Interface anzubinden. Die Protokolladapter sind Wrapper der Treiber der jeweiligen Funkprotokolle. Sie füttern die Abstraktionsschicht (HDM) von unten.

Jetzt stehen die Geräte sprachunabhängig als Objekte in OSGi zur Verfügung, und Softwaremodule beziehungsweise Apps können diese schalten oder Daten auslesen.

Allgemeine Beispielarchitektur für M2M und IoT (Abb. 2)

(ane)