1
votes

I want to compile and run a simple Hello World program that declares and calls a native print method (defined in C++) from Java.

HelloCPP.java

class HelloCPP{
    private native void print();
    public static void main(String [] args){
        new HelloCPP().print();
    }
    static{
        System.loadLibrary("HelloCPP");
    } 
}

HelloCPP.cpp

#include <jni.h>
#include<iostream>
#include "HelloCPP.h" 
using namespace std;

extern "C" 
JNIEXPORT void JNICALL Java_HelloCPP_print(JNIEnv *env, jobject obj){
    cout << "Hello World from C++!" << endl;
    return; 
}

In the command prompt I run the following:

  • javac HelloCPP.java
  • javah -jni HelloCPP
  • 86_64-w64-mingw32-g++ -c -I"C:\Java\jdk1.8.0_171\include" -I"C:\Java\jdk1.8.0_171\include\win32" HelloCPP.cpp
  • x86_64-w64-mingw32-g++ -shared -o HelloCPP.dll HelloCPP.o
  • java -Djava.library.path=. HelloCPP

Then the infamous DLL linking/loading error

Exception in thread "main" java.lang.UnsatisfiedLinkError:<"MyProjectDirectory">\HelloCPP.dll: Can't find dependent libraries at java.lang.ClassLoader$NativeLibrary.load(Native Method) at java.lang.ClassLoader.loadLibrary0(ClassLoader.java:1941) at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1857) at java.lang.Runtime.loadLibrary0(Runtime.java:870) at java.lang.System.loadLibrary(System.java:1122) at HelloCPP.(HelloCPP.java:8)

Attempted Solutions

  • java -Djava.library.path=. HelloCPP is supposed to check the current project directory which is where the dll is built and should link fine
  • Tried copying the dll into a another folder and adding that folder directory to the path system environment variable
  • Used the Dependency Walker and noticed HelloCPP.dll is looking for libstdc++-6.dll and other dlls
  • Tried copying these drivers into the same directory and then it causes a chain reaction looking for additional dlls
  • Tried adding commands like -static-libstdc++

Additional Notes

  • I can run this exact program with the native method in C and using x86_64-w64-mingw32-gcc, the DLL is found, linked, loaded and program runs fine
  • x86_64-w64-mingw32-g++ was downloaded through Cygwin
  • Switched to x86_64-w64-mingw32-g++ because I was having the same issue as Cygwin compilation error Problematic frame: # C [cygwin1.dll+0xd6d47] using JNI when using g++
  • Currently using Sublime text editor to write my Java and C++ files, then compiling through command prompt
  • If anyone can recommend me a good IDE to use for dev with JNI that would be great
  • First time posting hopefully did not miss anything important, have spent much time going through already asked questions
1
Cygwin is a layer for linux (?) programs. This lay mey not used by windows programs like java. Use a native windows compiler for the JNI part.Konrad
@Konrad I thought Cygwin is a set of tools that essentially give a Linux like environment for Windows. Do not believe the compiler I am using is restricted to Linux, as I have been able to compile other non JNI C/C++ sources without issueRichard S
What version of Java are you using? If it's a 64 bit version you can't load a 32 bit library with it. Afaik the compiler you're using always produces 32 bit binaries.Jorn Vernee
@JornVernee Thank you. I had followed some other resource to supposedly check whether the DLL that was being built was 64bit. Switching to MinGW-W64 compiler has solved the issue for me. sourceforge.net/projects/mingw-w64/files/… in case anyone needs itRichard S

1 Answers

1
votes

Java Code: helloworld.java

class helloworld{
    public native void hello();

    static {
            System.loadLibrary("hello");
    }
    public static void main(String args[]){
            new Helloworld().hello();
    }
}

cpp code: hello.cpp

#include<iostream>
#include "helloworld.h"
using namespace std;
JNIEXPORT void JNICALL Java_helloworld_hello(JNIEnv *env, jobject obj)
{
    cout<<"Hello World";

    return;
}

Commands

javac -h . helloworld.java
g++ -I /usr/lib/jvm/java-8-oracle/include/ -I /usr/lib/jvm/java-8-oracle/include/linux/ hello.cpp -shared -o libhello.so -fPIC
java -Djava.library.path=. helloworld