Using Native Code

These tutorials explains the different possibilities to use native (i.e., non-Java) code in your application. There are at least four methods to do this and we have made separate tutorial for each of the methods.

Example: A Watchdog

As an example, we integrate a watchdog in an application that runs on a Raspberry Pi. The Raspberry Pi comes with a hardware-based watchdog and we will use C or C++ code to access it. We cannot use Java directly because we need the ioctl() system call to access it.

A watchdog timer is a special kind of timer commonly found on embedded systems that detects when the running software is not operating correctly, i.e hung up on some task. The watchdog timer is basically a countdown timer that counts from some initial value down to zero. When zero is reached, the watchdog timer understands that the system is hung up and resets it. Therefore, the running software must periodically update the watchdog timer with a new value to stop it from reaching zero and causing a reset. When the running software is locked up doing a certain task and cannot update the watchdog timer, the timer will inevitably reach zero and a reset will occur.

It is good practice to have a hardware watchdog on embedded systems.

Although linux does have a watchdog daemon that can send heartbeats to the watchdog to monitor if the OS is hanging, the preferred way of integrating a watchdog is to access it from your main application when it operates correctly. Do not make the mistake of updating the watchdog from a separate timer thread, but make sure updates comes from your “main” loop.

Prerequisites

To run these particular demos you will need Raspberry Pi with latest version of Raspbian installed.

Do these preparations

  1. Make sure gcc is installed, try gcc -v
  2. Load the watchdog kernel module sudo modprobe bcm2708_wdog
  3. If you want this change to survive a reboot you need to add it to kernel modules file: sudo nano /etc/modules

Alt text

Note that adding the kernel module does not enable the watchdog.

Tutorials

These are the tutorials for the different methods:

  1. Separate process tutorial: foreign-code-process
  2. BridJ (C++) tutorial: foreign-code-bridj
  3. JNA tutorial: foreign-code-jna
  4. JNI tutorial: foreign-code-jni

Comparison

JNA
  • This is our preferred solution for C and C++.
  • With JNA all or most of your work is done in Java.
  • All the tedious memory allocation/deallocation is hidden by the JNA library.
  • Robust and wellproven technology.
JNI
  • With JNI your get bare-bones interface with no "behind the scenes" magic.
  • If you are concerned about overhead and performance you should use JNI, but then you should verify the performance issue by measuring both a JNI and a JNA implementation.
  • If you are interfacing other languages than C or C++ you must use JNI. Here is a random list of other languages: (We have not tested any of these libraries.)
BridJ
  • BridJ gives you access directly to C++ classes, but our experience is that you cannot use any C++ class and make an interface to Java directly, particularly other header files cause JNAerator to not work properly.
  • You might be better off making a C-wrapper of your C++ classes and use JNA instead. That way your Java/C++ interface will change less frequent and be easier to maintain.
  • There are other tools or libraries promising the same functionality as BridJ, such as javacpp or swig. (We have not tested them.)
Separate Processes
  • Works in case you do not have access to the source code.
  • Using separate processes is a quick and dirty solution that may work well in a test environment, but it very brittle.
  • Transferring larger amount of data back and forth from/to the calling Java method makes the solution even more brittle, the only acceptable solution is socket communication/shared memory, but then this is not a relevant example anymore.