# JNI short tutorial

#### 1 Write a Java class that uses C codes

{% code title="CraftJNI.java" %}

```java
public class CraftJNI {
  static {
    System.loadLibrary("hello"); // Load native library hello.dll (windows)
                                 // or libhello.so (Unixes) at runtime.
                                 // This library contains a native method sayHello()
                                 
  }
  
  // Declare an instance native method sayHello() which receives no parameter
  // returns void
  private native void sayHello();
  
  // Test Driver
  public static void main(String[] args) {
    new CraftJNI().sayHello(); // Create an instance and invoke native method
  }
}
```

{% endcode %}

#### 2 Compile Java program `CraftJNI.java`

```bash
javac -h . CraftJNI.java
```

{% code title="CraftJNI.h" %}

```bash
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class CraftJNI */

#ifndef _Included_CraftJNI
#define _Included_CraftJNI
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     CraftJNI
 * Method:    sayHello
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_CraftJNI_sayHello
  (JNIEnv *, jobject);

#ifdef __cplusplus
}
#endif
#endif
```

{% endcode %}

To know more about the generated class file

```bash
javap -verbose CraftJNI.class
```

#### 3 Implement C program

{% code title="CraftJNI.c" %}

```c
#include <jni.h>   // Standard JDK provided header
#include <stdio.h> // Standard C IO header
#include <CraftJNI.h> // Generated header

JNIEXPORT void JNICALL Java_CraftJNI_sayHello(JNIEnv *env, jobject thisObj) {
  printf("I am in C code \n");
  return;
}

```

{% endcode %}

#### 4 Compile C program

```bash
gcc -fPIC -I"." -I"$JAVA_HOME/include" -I"$JAVA_HOME/include/linux" \
   -shared -o libhello.so CraftJNI.c
```

```bash
> java -Djava.library.path=. CraftJNI
I am in C code
```

### Troubleshooting

#### Error 1: class file has wrong version

```bash
> javah CraftJNI.class
Error: cannot access CraftJNI
  bad class file: ./CraftJNI.class
    class file has wrong version 55.0, should be 52.0
```

Reason: `javah` is not available with Java 11

```bash
> java -version
openjdk version "11.0.9.1" 2020-11-04
OpenJDK Runtime Environment (build 11.0.9.1+1-post-Debian-1deb10u2)
OpenJDK 64-Bit Server VM (build 11.0.9.1+1-post-Debian-1deb10u2, mixed mode, sharing)

> javac -version
javac 11.0.9.1

> javah -version
javah version "1.8.0_252"

> whereis java
java: /usr/bin/java /usr/share/java /usr/share/man/man1/java.1.gz

> ls /usr/share/man/man1 | grep java*
java.1.gz
javac.1.gz
javadoc.1.gz
javah.1.gz
javap.1.gz
```

#### Error 2:

```bash
> java -Djava.library.path=. CraftJNI
Exception in thread "main" java.lang.UnsatisfiedLinkError: no hello in java.library.path: [.]
        at java.base/java.lang.ClassLoader.loadLibrary(ClassLoader.java:2670)
        at java.base/java.lang.Runtime.loadLibrary0(Runtime.java:830)
        at java.base/java.lang.System.loadLibrary(System.java:1873)
        at CraftJNI.<clinit>(CraftJNI.java:4)
```

### References

1. JNI reference docs - <https://docs.oracle.com/javase/8/docs/technotes/guides/jni/spec/jniTOC.html>
2. Some of the code is shamelessly copied from <https://www3.ntu.edu.sg/home/ehchua/programming/java/JavaNativeInterface.html>


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://i.janardhanpulivarthi.com/season-1/jni-short-tutorial.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
