Skip to content

Java

The documentation for using Java is divided into 3 parts:

  • this general presentation, to explain the features, the limitations and the configuration of the Java Virtual Machine.
  • the list of the native classes that cover both the 'classic Java classes', and those specific to the TapNLink environment
  • how to use the Raisonance debugger. If you write just a few lines of Java, you will not need anything else but Iotize Studio. However, if you plan to edit a real Java program, 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.

Preamble

For the moment, the Java Virtual Machine is only available in TnlFIW103 and TnlFIL103 TapNlink (or TapNPass) models (NFC+WiFi+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 available in the current firmware.

Features

IoTize Studio includes a reduced version of Java Virtual Machine which is optimized to allow you 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).

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

The TapNLink Java implementation is not full Java, but IoTize tried to offer all functionalities that could be needed as complement for the TapNLink machine itself. 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. 10µs per Java instruction).

Main limitations of the IOT_JVM

You have to consider the following limitations:

  • 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.

  • only UTF-8 encoding is supported for characters

  • link is done statically when calling IOT_JVM.

General principles of the IOT_JVM

IOT_JVM supports multiple classes that have to be linked statically (the standard JVMs perform a dynamic link). 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 on the '.class' files. This is done automatically when a Java file is specified into Studio (or within a Ride-7 project).
Native subclasses Some predefined subclasses, [native](./native.md), 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?

Prerequirements

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

IMPORTANT NOTE: 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\SensorDemo.java"

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, - 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 Java 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.

image

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 Java 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.

  • Stack size (number of words): this is the number of items (32 bit each) reserved for the stack.

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.

How to debug

If you decide to write more than 100 lines of Java code, you will probably need to debug your code (at least to look at your memory consumption). A free debugger is available on the Raisonance web site.

Things to know

  • 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.

Warning

  • Do NOT create a TapNLinkVar object inside the onCheck/onEvent methods. TapNLinkVar MUST be declared in the constructor.
  • Do NOT call setValue() method for TapNLinkVar objects that are not yet initialized.
  • Do NOT set a null value for the periodicity of the TapNLinkVar objects.

Try-catch

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

java try { // Your code } catch(TapNLinkException error) { // If your code generate exception then he passed here }