MicroEJ Runtime

Language

MicroEJ allows to develop Applications in the Java® Language Specification version 7 with some limitations, and supports code extensions written in JavaScript.

Basically, Java source code is compiled by the Java compiler [1] into the binary format specified in the JVM specification [2]. This binary code is linked by a tool named SOAR before execution: .class files and some other application-related files (see Classpath chapter) are linked to produce the final binary file that the Core Engine will execute.

Note

When opened in the SDK, make sure that the Compiler Compliance Level of your project is set to 1.7 to ensure the bytecode produced by the Java compiler is compatible with MicroEJ. The Compliance Level can be changed from the menu: Window > Preferences > Java > Compiler.

[1]The JDT compiler from the Eclipse IDE.
[2]Tim Lindholm & Frank Yellin, The Java™ Virtual Machine Specification, Second Edition, 1999

Core Libraries

This section describes the core libraries which make up the runtime. Theses Foundation Libraries are tightly coupled with the Core Engine.

Embedded Device Configuration (EDC)

The Embedded Device Configuration specification defines the minimal standard runtime environment for embedded devices.

This module is always required in the build path of an Application project; and all others libraries depend on it. This library provides a set of options. Refer to the chapter Standalone Application Options which lists all available options.

It defines all default API packages:

Documentation Link
Java APIs https://repository.microej.com/javadoc/microej_5.x/libraries/edc-1.3-api/
Module https://repository.microej.com/modules/ej/api/edc/

Use

The EDC API Module must be added to the project build file of the Application Project:

implementation("ej.api:edc:1.3.5")

Beyond Profile (BON)

This profile defines a suitable and flexible way to fully control both memory usage and start-up sequences on devices with limited memory resources. It does so within the boundaries of Java semantics. More precisely, it allows:

  • Controlling the initialization sequence in a deterministic way.
  • Defining persistent, immutable, read-only objects (that may be placed into non-volatile memory areas), and which do not require copies to be made in RAM to be manipulated.
  • Defining immortal, read-write objects that are always alive.
  • Defining and accessing compile-time constants.
Documentation Link
Java APIs https://repository.microej.com/javadoc/microej_5.x/apis/ej/bon/package-summary.html
Specification https://repository.microej.com/packages/ESR/ESR-SPE-0001-BON-1.2-G.pdf
Module https://repository.microej.com/modules/ej/api/bon/

Use

Add the following dependency to the project build file of the Application Project to use the BON API Module:

implementation("ej.api:edc:1.3.5")

Simple Native Interface (SNI)

SNI provides a simple mechanism for implementing native Java methods in the C language.

SNI allows you to:

  • Call a C function from a Java method.
  • Access an Immortal array in a C function (see the Beyond Profile (BON) to learn about immortal objects).

SNI does not allow you to:

  • Access or create a Java object in a C function (except byte arrays).
  • Access Java static variables in a C function.
  • Call Java methods from a C function.

SNI also provides some Java APIs to manipulate some data arrays between Java and the native (C) world.

Documentation Link
Java APIs https://repository.microej.com/javadoc/microej_5.x/apis/ej/sni/package-summary.html
Specification https://repository.microej.com/packages/ESR/ESR-SPE-0012-SNI_GT-1.2-I.pdf
Module https://repository.microej.com/modules/ej/api/sni/

Please refer to Simple Native Interface (SNI) section for more details.

Kernel & Features (KF)

The Kernel & Features semantic (KF) extends the runtime for managing Multi-Sandboxed Applications.

Please refer to the Kernel & Features Specification for more details, the Multi-Sandbox capability of the Core Engine and more generally the Kernel Developer Guide chapter.

Scheduler

The Core Engine features a Green Threads model. The semantic is as follows:

  • preemptive for different priorities,
  • round-robin for same priorities,
  • “priority inheritance protocol” when priority inversion occurs. [3]

Threads stacks automatically adapt their sizes according to the thread requirements: once a thread terminates, its associated stack is reclaimed, freeing the corresponding RAM memory.

[3]This protocol raises the priority of a thread that is holding a monitor needed by a higher-priority thread, to the priority of that higher-priority thread (until exiting the monitor).

Garbage Collector

The Core Engine includes a state-of-the-art memory management system, the Garbage Collector (GC). It manages a bounded piece of RAM memory, devoted to the Java world. The GC automatically frees dead Java objects, and defragments the memory in order to optimize RAM usage. This is done transparently while the Application keep running.

See also Garbage Collector options for more details.

Limitations

Primitive Types

Getting a Class instance of a primitive type is not supported:

  • boolean.class,
  • byte.class,
  • char.class,
  • short.class,
  • int.class,
  • long.class,
  • float.class,
  • double.class.

On Architecture 8.x, you will get the following dedicated error message:

Unsupported access to the Class instance of a primitive type (found 'boolean.class' in method 'com.mycompany.MyClass.myMethod()void')

On Architecture 7.x you will get the following default error message:

No such field TYPE at com/mycompany/MyClass.myMethod()V.

Architecture Characteristics

The Application can retrieve some characteristics of the Architecture on which it is running. Architecture characteristics are automatically provided as constants. Here are the most notable ones:

  • com.microej.architecture.capability=[tiny|single|multi]: Core Engine Capability
  • com.microej.architecture.name=[architecture_uid]: Architecture name.
  • com.microej.architecture.level=[eval|prod]: Usage level (Evaluation or Production).
  • com.microej.architecture.toolchain=[toolchain_uid]: Toolchain name.
  • com.microej.architecture.version=[M.m.p]: Architecture version.

See also Architecture Naming Convention for more details.

The following code prints the formatted Architecture characteristics on standard output. You can copy-paste and adapt it to your needs.

String name = Constants.getString("com.microej.architecture.name");
String version = Constants.getString("com.microej.architecture.version");
String buildLabel = Constants.getString("com.microej.architecture.buildLabel");

String usage = Constants.getString("com.microej.architecture.level");
String usageStr;
if (usage.equals("prod") || usage.equals("dev")) {
  usageStr = "Production";
} else if (usage.equals("eval")) {
  usageStr = "Evaluation";
} else {
  usageStr = usage;
}

String capability = Constants.getString("com.microej.architecture.capability");
String capabilityStr;
if (capability.equals("multi")) {
  capabilityStr = "Multi";
} else if (capability.equals("tiny")) {
  capabilityStr = "Tiny";
} else if (capability.equals("single") || capability.equals("mono")) {
  capabilityStr = "Mono";
} else {
  capabilityStr = capability;
}

String isaStr = Constants.getString("com.microej.architecture.architecturePrintableName");
String toolchainName = Constants.getString("com.microej.architecture.toolchainPrintableName");
String toolchainFullName = Constants.getString("com.microej.architecture.toolchain");

System.out.println("- Name:                         " + name);
System.out.println("- Version:                      " + version + " (" + buildLabel + ")");
System.out.println("- Usage:                        " + usageStr);
System.out.println("- Core Engine Capability:       " + capabilityStr + "-Sandbox");
System.out.println("- Instruction Set Architecture: " + isaStr);
System.out.println("- Compilation Toolchain:        " + toolchainName + " (" + toolchainFullName + ")");