5 Minutes to Understand a Kernel

Keeping embedded software manageable at scale is no small task. When you manage fleets of products, you have to deal with a growing list of challenges:

  • rebuilding and reflashing loads of targets,
  • monitoring and validating software components and their interactions,
  • maintaining compatibility across multiple hardware platforms,
  • ensuring compliance with regulatory standards,
  • addressing security vulnerabilities,
  • and more.

How do you tackle all of that without slowing your development team down? You need a technological solution that empowers your choices and complies with enforced guidelines without impeding on your capacity to be flexible. That is where the MICROEJ Kernel comes into play.

A MICROEJ Kernel is a Standalone Application that implements the ability to be extended to produce a Multi-Sandbox Executable.
But what exactly is a Multi-Sandbox Executable? Think of a framework that manages several concurrent applications, controls what they can access through API filtering and services management, and keeps their resources and memory spaces isolated from one another. A MICROEJ Kernel achieves this by exposing a custom Runtime Environment, dynamically loading new code, and linking new applications, called Sandboxed Applications, into dedicated memory spaces, all without requiring changes to the Kernel itself.

This article walks you through the key ideas behind a Kernel.

Lifecycle Management of Sandboxed Applications

Each Sandboxed Application runs with its own lifecycle, independently from the others. It can be installed, started, stopped, and uninstalled without rebuilding or reflashing the entire device.
The AppConnect library provides dedicated APIs for this purpose. That gives you flexibility at runtime, but it also raises another question: what about compatibility?

Before installing a Sandboxed Application, the Kernel verifies that it is compatible with the running Kernel. Installation only proceeds if they match, or if the Kernel is declared compatible according to the rules defined in the Feature Portability Control section.

Kernel APIs and Runtime Environment

The Kernel controls which APIs are accessible to Sandboxed Applications at build time through Kernel APIs. By default, nothing is exposed unless explicitly declared. Think of it as a contract that Sandboxed Applications compile against: the Kernel defines a set of allowed capabilities (with a granularity as fine as a Java field), and Sandboxed Applications can only use what is on that list.

This is especially valuable when multiple teams or third-party developers build Sandboxed Applications for the same device without having access to the Kernel code. The team that maintains the Kernel decides what is shared and what is off-limits.

Kernel APIs can be provided individually or as part of a Runtime Environment that aggregates multiple APIs together.

Security Policy Enforcement

Beyond controlling API access at build time, the Kernel enforces runtime restrictions through a Security Manager. When a Sandboxed Application attempts to use a protected API, the Kernel intercepts the call and checks whether it has permission.

Security policies can be defined through a permission file that declares what each Sandboxed Application is allowed to do, or through a custom handler that evaluates permissions dynamically. This gives you a practical way to run third-party applications on a device without giving them unrestricted access to the system.

Resource Manager

A misbehaving application, whether due to a bug or bad intent, should never be able to bring down the whole system. To prevent excessive resource usage, the Kernel relies on the Resource Manager to enforce limits on CPU, RAM, flash, and network bandwidth for each Sandboxed Application. If an application exceeds its quota, the Kernel steps in before it impacts the rest of the system.

Shared Interfaces (Inter-Application Communication)

Since each Sandboxed Application runs in its own isolated context, it cannot directly reference objects or call methods belonging to another Sandboxed Application. That is where Shared Interfaces come in: they provide an object communication bus based on Java interfaces that enables method calls across application boundaries without relying on Kernel APIs.

Communication follows a service-oriented pattern: a provider publishes an implementation to the service registry, and a consumer retrieves it by requesting the interface type. The registry returns a proxy that the consumer can invoke as if it held a direct reference. Method calls between applications can carry parameters and return values, and transfer rules govern how each type is handled when passed from one application to another.

Going Further

Happy coding!
The MicroEJ Team.