Skip to content

Java support

Oracle, Java, and MySQL are registered trademarks of Oracle and/or its affiliates. Other names may be trademarks of their respective owners.

The documentation for using the embedded JVM is divided into 3 parts:

  • this general presentation, to explain the features, the limitations and the configuration of the Virtual Machine.
  • the list of the native classes that cover both the 'classic classes', and those specific to the TapNLink hardware environment
  • how to use the Raisonance debugger. If you write just a few lines of code, you will not need anything else but Iotize Studio. However, if you plan to edit several hundred/thousand lines of code, you can download a powerful free environment to debug your application, either with a simulator or with a real time debugger that will be connected to your Tap through the lwM2M.


For the moment, the Virtual Machine is only available with TnlFIW103, TnLFIR203 and TnlFIL103 TapNlink (or TapNPass) models (NFC+WiFi+BLE, NFC+BLE and NFC+LoRa). It is also available on all Tapioca models and for TapNPass NFC+BLE+WiFi. New implementations will be soon available.

It has been introduced in 2020Q2 and we strongly recommend you to check the versions of your tap firmware and Studio. See update your firmware and the IoTize Studio download page. Note that your byte-code will not be executed by TapNLink if it calls some native methods that are not supported by the current firmware.


Duetware includes a Virtual Machine which has been optimized to:

  • analyze the data and make decisions to create alarms and perform data logging,
  • access the I/O signals or the communication peripherals: UART, I²C, CAN or SPI,
  • manage sensors or actuators through communication ports, ADC, counters,...
  • format MQTT messages, for example in JSON thanks to the JSON or String classes,
  • send and receive MQTT messages or other notifications,
  • use the TapNLink as a standalone device (without target) to control a simple sensor/actuator.

Java language offers the advantage of being understood by both the mobile apps developers and the embedded programmers, since its syntax is close to C/C++.

The TapNLink implementation is not fully compliant with Java (it can be considered as a subset), but IoTize tried to offer all functionalities that could be needed as complement for the TapNLink lwM2M machine. Indeed, the general syntax of the language is supported but some of the system classes are certainly missing.

If you really need to use a method that is not currently supported, please contact IoTize. We may find a workaround, or we may add this method to the next version of the firmware, but our goal is to keep a very light process so that the IOT_JVM can provide high performances:

  1. Very limited RAM usage (a few hundredth of bytes).
  2. Very limited FLASH footprint (around 60KB for the JVM + native classes).
  3. Very efficient execution (typ. 20µs per Java instruction).

Main limitations of the IOT_JVM

You have to consider the following limitations:

  • size: the current JVM uses 16-bit references. It means that the byte code and heap are both limited up to 65535 bytes. In reality, the available memory for most of the TapNLink models is less than 128KB. It also depends on the overall memory consumption (use of TLS, MQTT, ...).

  • the standard classes of the language are not all implemented. For the implemented classes, some methods may be missing. We have tried to implement most of the well known methods of the most important classes.

  • multi-threading, multiple-inheritance, low level networking are not supported,

  • only UTF-8 encoding is supported for characters,

  • link is done statically by calling IOT_JVM.

General principles of the IOT_JVM linker

IOT_JVM supports multiple classes that have to be linked statically. Refer to the examples in IoTize\IoTize Studio\Examples\JVM to get an idea of what you can do. You can also find several applications written in Java here.

Static link The main class has to provide the following methods (the constructor and *onEvent* are optional):
- void onCheck (int id) : this function is called periodically (depending of the periods declared for the TapNLink variables registration).
- void onException (final in errorcode, final int jpc, final int jsp : This function is called when an unhandled error occured (division by zero, stack overflow, ...). Note that other exceptions can also be handled locally using the try - catch syntax.
- void onEvent (Object data) : this function is called to notify your program that an event occured: MQTT message reception, external interrupt, ... This method is optional.
Other classes can be added either in the same file (inner classes) or as external classes. The Iotize linker tool (IOT_JVM.exe) must be called with the main '.class' file as argument. This is done automatically when a Java file is specified into Studio (or within a Ride-7 project).
Native subclasses Some predefined subclasses are provided to link this main class to the TapNLink resources and are executed as native code. Various classes to access the Input/Output of the extension ports are also available. Their declarations are in "IoTize Studio/bin/com/iotize/JVM" directory.
.bcb file The .bcb file is equivalent to the .class file generated by the JAVAC compiler, but it has been reformatted to make reading and execution easier in our simplified JVM. It is generated by the IOT_JVM.exe linker.
Mostly, it contains static tables that the JVM handles very efficiency. Most of the ASCII names of the declared objects are also removed in order to shrink the initial class file.

How to proceed?


If you don't have Oracle javac compiler, install Oracle OpenJDK suite to obtain javac.exe.


The embedded JVM is only tested with the version 1.8.0 of javac compiler. We recommend to install and use Open JDK 1.8 that is also used by Android Studio. Note that using another version of the JDK could rise errors such as "unsupported methods" for the String class handling. But if you have a more recent version, the version to be considered can be also specified by using the '-target' and '-source' arguments:
javac.exe -classpath "C:\Program Files (x86)\IoTize\IoTize Studio\JVM" -g -version -source 1.8 -target 1.8 ".\java_src\"

1. Create your .java file

We recommend two methods to create your Java file:

  • either you use the skeleton automatically generated by the Wizard when you create a new project in Iotize Studio,

  • or you take a copy of a java file from the examples and rename it to the name of your class.

Then you can either:

  • edit the file into Studio's Java editor : image

  • or work within Ride7 + Rkit-Java. This solution allows to debug your Java program.

  • or use your preferred editor and just launch the compiler from Studio.

Keep these import commands unchanged:

  • import com.iotize.jvm.*; // System classes (Variables)
  • import com.iotize.jvm.hal.*; // HAL drivers (UART)

Create a public class (with the same name as the file) and:

  • mandatory onException() and onCheck() methods
  • optionally a constructor and onEvent methods
  • and whatever other features you desire that are supported by IOT_JVM.

2. Compile and assemble your Class, and add to IoTize Studio configuration

Compile your Java class with javac.exe (image icon in Studio's Java Editor). The same command is also available in the main menu: "Configuration" | "Run Java compiler"

If you get an error message saying javac is not installed:
  1. Open the Start Windows.
  2. Search for *environment*, then select *Edit environment variables for your account*.
  3. Click on the *Path variable* and *Edit*.
  4. At the end of the variable value, type *;* then paste the pathname of the directory that contains the javac.exe. (e.g. *;C:\Program Files\Java\jdk-14.0.2\bin*)
  • Any compiler errors before the 2 ============= separator lines are javac call errors that must be resolved first. They are 'standard java errors' that must be fixed considering the Java language specification.
  • Errors after these lines are generated by IoTize 'IOT_JVM' linker utility. They generally indicate that the current code cannot be executed withing the TapNLink environment. Most frequent errors issued from iot_jvm.exe report calls to unsupported Java class or method. Contact IoTize support if you have problems.

Link the resulting TapNLink_User.class file using IOT_JVM.exe (in ‘IoTize Studio/bin’ folder) to check compliance with the IOT_JVM environment and produce a .bcb file. This is done automatically by Studio (or when using the RKit-Java under the RIDE7 Integrated Development Environment). If your project contains several classes, declare only the main file (e.g. the main class). The other files will be automatically loaded and added to the bcb file.

Check the again messages, and verify that your Tap's firmware is the same version as the most recent method (currently version 1.106). If it isn't, please update your firmware to obtain the most recent methods.

4. Add to IoTize Studio configuration

Add the path of either the .bcb or the .java files to IoTize Studio in Tap / JVM Custom Code File.


5. and specify the parameters of the running environment

There are 3 parameters to specify:

  • Minimal code size(KB): You could leave '0' as minimal code size (MIN_SIZE). In this case, the resulting bcb file will be saved at its real size (REAL_SIZE). Otherwise, the bcb file could be extended with zeroes to reach MIN_SIZE.
    In other words, we have: BCB_SIZE = MAX(MIN_SIZE, REAL_SIZE).
    Why extending the bcb size ? When debugging within Ride-7, if you want to modify the byte code after a minor change, the code will be overwritten in the previously allocated space. If your new code is larger than the initially allocated space, debugging will not be possible. Thus, we recommend to declare a few KB more than REAL_SIZE as long as you are in the debugging stage.

  • Heap size(KB): an unique global buffer is allocated in RAM for the need of the JVM data. This buffer contains the Heap, but also the internal variables and the stack. Once your development will be finalized, you could adapt the Heap size in order to save memory (the Ride-7 debugger displays the available memory in the Main Register window).

  • Stack size (number of words): this is the number of items (32 bit each) reserved for the stack. Note that the stack is allocated from the HEAP during the initialisation stage.

We recommend using first the simulator to check that the above specified values make sense for your program. When executing the Java program, both the BCB and the Heap will be located in the RAM of the TapNLink MCU and you should adapt these values to avoid a lack of memory.

Things to know

  • Do NOT create a class that inherits from native classes. Inheritance is supported only from user's classes.

  • There are two types of InTap variables: volatile and non-volatile. The contents of non-volatile InTap variable is lost when resetting the Tap (stored into volatile memory).

  • In case two TapNLinkVar variables need simultaneously to be checked, the order of the declarations of the TapNLinkVar variables defines the priority.

  • The value of a TapNLinkVar will NOT be initialized at the constructor, but just before the first call to onCheck(). For example, if you define a TapNLinkVar object with a periodicity of one hour, getValue() will return a dummy value until onCheck() is called for this variable (after one hour). A workaround consists in reading directly the variable (either inTap or external) through a call to the lwM2M.

  • If you set a null value for the periodicity of a TapNLinkVar object, the onCheck method will not be called for this variable.

  • try/catch actually working with TapNLinkException to contains error number.

try {

  /* Your code */

} catch(TapNLinkException error) {

  /* If your code generate exception then it passed here */



Various examples are available into "IoTize\IoTize Studio\Examples\JVM\" when you install Iotize Studio. You will also find a simple example that demonstrates how to connect an I2C sensor here.
For more complex examples, you can refer to the support site.

How to debug

A few lines are often sufficent to be the perfect complement to the lwM2M machine. But if you decide to write more than 100 lines of code, you will probably need to debug your code (at least to look at your memory consumption). For this purpose, a free debugger environment is available on the Raisonance web site.

Native classes

The native classes cover both the classic classes of the language, and those specific to the TapNLink hardware environment.