Why use Java language at all?
The Java technology has successfully been used and deployed in servers, desktops, smartphones/tablets (through Google Android), and highly secure smart cards because of advantages offered by four main elements:
- The formally proven 32-bit processor (mostly implemented in software and called “Java virtual machine”) securely decouples binary software from hardware, ensuring binary (i.e., no source rebuild necessary) portability and maintainability of software code across hardware. This allows for deployment—dynamically or not—binary code securely across different devices.
- The programming language captures all of the best and widely used software engineering practices from object-oriented programming (OOP) that deliver higher productivity and better maintenance. For example, there’s the built-in, very important notion of application programing interfaces (APIs) materialized by the keyword “interface.”
- A rich set of documented APIs and libraries offers ready-to-use components (i.e., code) and services (i.e., objects) so that developers don’t reinvent the wheel and do more reuse, resulting in shorter time to market and a focus on developing value-added business features.
- The runtime environment provides advanced software execution and debug capabilities to developers, such as binary-code verification, sound multitask programming/multicore memory management, garbage collection for RAM optimization, runtime checks with exception handling, and runtime stacks crawling for permission checks, enabling reliable and robust architectures.
Today the Java language is the number one programming language, with millions of software architects and designers, as shown by two independent surveys:
Java Platforms for IoT Enable Application Portability
Developers of smaller embedded or IoT devices have been using legacy technologies and tools largely based on C language programming and real-time operating systems (RTOSs). But embedded C and RTOS experts are hard to find (maybe a few 10,000 or so worldwide) and tend to focus on low-level, hardware-dependent software development—drivers and board support packages (BSPs) for operating system (OS) bring-up.
For higher-level, hardware-independent software programming, developers naturally turn to the Java language to benefit from the same advantages enjoyed by developers for PCs and mobiles. They can also tap into a worldwide pool of 10 million trained and skilled engineers.
The Java software execution environment enables developers to write code that can be ported across the fragmented hardware and diverse low-level software characterizing the embedded/IoT landscape. On PCs and servers, developers mainly address two operating systems—Microsoft Windows and the open-source Linux—on the dominant Intel architecture. On smartphones and tablets, developers target either Google Android, which mostly runs on ARM architectures, or Apple iOS for a single hardware.
Embedded platforms rely on a variety of commercial, open-source or in-house RTOS, libraries (e.g., TCP/IP; file systems; SSL/TLS; serial I/O; communication stacks for USB, CAN, Bluetooth, LTE and other wireless networks), and compiler/linker toolchains. All combinations of the above software elements have to run on a large variety of 32-bit instruction set architectures (ISAs), including ARM Cortex-M and Cortex-A, MIPS32, POWER, TriCore, PIC32, AVR32, RX, etc.
1. Vertical integration requires the application to be ported to each combination of ISA, RTOS, libraries, and compiler/linker, as opposed horizontal integration enabled by the Java platform.
Figure 1 illustrates a “vertical-integration” approach, where the application needs to be ported to each combination of ISA, RTOS, libraries, and compiler/linker. This is in contrast to a “horizontal-integration” approach enabled by a Java platform, where the virtualization layer makes the application portable across all ISA/RTOS/compiler combinations.
The vertical-integration approach leverages a limited developer community; lots of effort and money is spent in middleware (RTOS + libraries) development and integration. The horizontal-integration approach taps into the largest developer community in the world and seriously reduces middleware integration work (the Java platform provides pre-integrated services and libraries). Furthermore, Java applications can be written for the same API across all underlying hardware and runtime configurations.
Java Eases Development of IoT End-to-End Apps
IoT obviously means connectivity to the Internet, but it also means integration to standardized IT client-server architectures, protocols, and frameworks. This integration allows for interaction with business/enterprise services and monetization of data generated by devices and applications (Fig. 2).
IoT devices interact with cloud platforms through standard protocols. It enables delivering new services through applications downloaded from online stores, which creates new business opportunities after devices are sold and deployed in the field. IoT devices also send data streams to cloud-based data-analytics servers in order to exploit information on their use. Lastly, IoT devices interact with the physical world through sensors and actuators by leveraging standards (e.g., Android hardware API).
2. An end-to-end IoT infrastructure allows interaction with business/enterprise services, which enables monetization of data generated by devices and applications.
Most cloud and IoT frameworks, such as MQTT, CoAP, XMPP, LWM2M, and OMA-DM, have an implementation written in the Java language. The Java platform provides standard libraries and APIs for accessing elements that are largely used in enterprise applications: communicating through Internet protocol (IP)-based networks, calling REST API over HTTPS, manipulating JSON and XML data formats, interfacing with data bases, etc. Using the same language on cloud and edge sides (the embedded/IoT devices) makes it easy to develop, debug, and deploy distributed IoT end-to-end (from sensors to cloud) applications.
Requirements for Embedded/IoT Java Platforms
There are multiple implementations of Java platforms, which translates into 20 billion Java platforms currently being used worldwide. These include:
- Java EE/SE for servers and desktops (on systems with typically several gigabytes of RAM and disk)
- Android for smartphones and tablets (on systems with typically 1 GB of RAM/8 GB of flash)
- Android Wear for high-end wearables (512 MB of RAM/4 GB of flash)
- Brillo for high-end IoT (32 MB of RAM/128 MB of flash)
- Java ME for high-end embedded (>2 MB of RAM/flash)
- MicroEJ OS for cost-effective, low-power embedded, IoT, wearables (96 kB to 2 MB of flash, 4 to 512 kB of RAM)
- Java Card for smart cards (similar memory constraints as above)
The main success factor for embedded/IoT/wearables is the cost, largely driven by hardware: processors, co-processors like floating point unit (FPU) or graphical processing unit (GPU), memory plus storage, and communications. Cost-driven devices with a total bill of materials (BOM) less than $30 can’t afford gigahertz processors and gigabytes of RAM/flash.
Smartphones and tablets have created expectations and uses that are becoming mandatory in IoT devices, e.g., connectivity, interactivity, customization, apps, and web services. Implementations of Java platforms have to optimize performance and footprint while delivering all of the features required by IoT devices.
The above constraints and expectations result in a set of requirements for Java platform implementation on wearable/IoT/embedded:
Processor: The platform should be able to run on a single-core microcontroller unit (MCU) with a minimum of 30 kB of flash, with no memory management unit (MMU) and potentially no FPU. It should support most popular ISAs—ARM Cortex-M family, from M0 to M7, up to Cortex A, and other architectures (MIPS, AVR, RX, TriCore…).
RAM: The platform should be able to run with a minimum of 16 kB of RAM for the whole system.
ROM/flash: The platform should be able to run with a minimum of 256 kB, and execute code in place (no need to copy code to RAM).
Scalable: The platform should not provide a monolithic block of libraries, but rather a modular implementation so that unneeded elements can be trimmed out to save memory.
Storage: The platform should be able to run with no mass storage (HDD/SSD/SD card) and without a file system by default. If a file system is needed, it should support file systems in RAM and flash (as well as SD card if the system can afford it).
RTOS: The platform should be able to run without a RTOS (a.k.a. “bare metal”: in scheduler-based mode) or on top of a small real-time kernel or RTOS (not Linux). The platform must ensure the same scheduling policy across all architecture ports without depending on the underlying RTOS task policy (i.e., code runs the same across all architectures).
Memory: The platform should provide optimized incremental garbage collection with tiny, hard, real-time compatible jitter.
Virtual processor: The platform should have very low overhead (a few kilobytes) and be optimized for the target architecture (ISA), application binary interface (ABI), and C toolchain. It should be portable to all combinations of the ISA/ABI/toolchain. It should not rely on a just-in-time (JIT) compiler, since it requires too much RAM (code is compiled on the fly in the target’s memory). To offer the best software code execution speed and memory footprint ratio, the platform should provide mixed optimization between the ahead-of-time (AOT) compiler (code is pre-compiled on the host before it’s loaded into the target’s memory) and direct implementation of the core language library in machine code. It should provide predictive thread scheduling as seen above. It should offer controlled reflective capabilities (from Wikipedia: “the ability of a computer program to examine and modify its own structure and behavior at run-time”) to save flash/RAM.
Native interface: The platform should provide an optimized interface with C thanks to a zero copy buffer strategy, and a shared heap between C and Java programs.
Boot time: The platform should boot in a few milliseconds, through a “clean” boot execution sequence with no “random” lazy initialization (from Wikipedia: “the tactic of delaying the creation of an object, the calculation of a value, or some other expensive process until the first time it is needed”).
Persistent data management: The platform should manage different types of objects that can be immutable (in flash/ROM memory), immortals, and regular (that can die).
Graphics: The platform should be able to run with no graphical display and no console (no keyboard/pointing device). If a graphical user interface (GUI) is required, it should be able to run with no GPU on top of a low-level 2D graphics library and a frame-buffer driver (no OpenGL or other higher-level graphics lib). It should support displays with all forms (square, rectangle, round…), resolutions, and color depth (1 bit to 24 bits). It should support touchscreens (all technologies) with multi-touch gestures. It should provide an optimized library of widgets, a tiny string display engine with anti-aliasing, and transparency support to render fonts.
Peripherals: The platform should access MCU peripherals with a simple and generic API for controlling digital-to-analog converters (DACs), analog-to-digital converters (ADCs), pulse-width-modulation (PWM) signals, general-purpose inputs/outputs (GPIOs)…
Connectivity: The platform should support embedded/IoT wired and wireless standards, e.g., Ethernet, Bluetooth, BLE, 802.15.4, USB, Z-Wave, ZigBee, RFID, NFC, DLSM/COSEM, CAN, various fieldbus, etc.
Network: The platform should support embedded UDP-TCP/IP v4/v6 stacks, Thread, 6LoWPAN, CoAP, MQTT…
Security: The platform should support SSL/TLS and DTLS for secured communications and cryptography for secured data storage and authentication (hard and soft with protocols such as OAuth).
Dynamic binary-code download: The platform should be able to load binary code on the fly without reset/re-flash, and without rebuild to avoid lag time and extra RAM requirements.
Multi-app: The platform should ensure secure execution of code with strong (potentially certified EAL5) isolation between apps (without MMU). It should ensure no interdependencies between apps (no link-time error when loading) and manage secure access of apps to system resources and API.
Accurate simulators on desktop: Simulators should use the very same resources (images, font, data…) as the embedded application.
Device management: The platform should be able to manage a fleet of devices with standards like TR-069, OMA-DM, and LWM2M.
To support embedded/IoT cost-effectiveness resulting in strong technical constraints, Java platforms for embedded/IoT/wearable devices need to follow a set of requirements that make them unique compared to Java implementations on servers, desktops, and mobile and high-end embedded systems.
The Java language, as the number one programming language, is naturally used by IoT software developers to create hardware-independent applications. It offers all of the necessary facilities for creating IoT end-to-end business applications and associated ecosystems, from sensors to cloud, based on standard protocols and frameworks.
Article was originally published on Electronic Design.