Chirag
Chirag

Reputation: 565

Java Native Method, gone something wrong

I just tried new to learn native methods in java today. I successfully loaded the Native.dll file successfully but having the problem in method call, also I am unable to figure out what is happening wrong.

My snippet code are:

NativeTest.java

package javaapplication2;

import java.io.File;
import java.util.Scanner;
/**
 *
 * @author Chirag
 */

public class NativeTest {

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        System.out.println("Loading Library nativeLib");
        try {
            Native n = new Native();
            System.out.println("Loading success");
            System.out.print("Enter a number to get cube: ");
            int x = sc.nextInt();
            System.out.println(x + " * " + x + " * " + x + " = " +       n.cubecal(x));
        } catch (Exception e) {
            System.out.println("Error loading native library");
            e.printStackTrace();
        }
    }

}

class Native {

    static {
        System.setProperty("java.library.path", new File("").getAbsolutePath());
//        try {
//            Field fieldSysPath = ClassLoader.class.getDeclaredField("sys_paths");
//            fieldSysPath.setAccessible(true);
//            fieldSysPath.set(null, null);
//        } catch (Exception e) {
//        }
        String arch = System.getProperty("sun.cpu.isalist");
        if (arch.trim().equalsIgnoreCase("amd64")) {
            System.loadLibrary("Native");
        } else {
            System.loadLibrary("Native");
        }
    }

    public native int cubecal(int x);

}

Compiled class by javac NativeTest.java

and makes the header file by javah Native

Native.h

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

#ifndef _Included_Native
#define _Included_Native
#ifdef __cplusplus
extern "C" {
#endif
    /*
    * Class:     Native
    * Method:    cubecal
    * Signature: (I)I
    */
    JNIEXPORT jint JNICALL Java_Native_cubecal
        (JNIEnv *, jobject, jint);

#ifdef __cplusplus
}
#endif
#endif

and one more snip

Native.cpp

#include "stdafx.h"
#include "Native.h"


JNIEXPORT jint JNICALL Java_Native_cubecal
    (JNIEnv *env, jobject obj, jint val){
        return val * val * val;
}

after all of this snip I am getting this error after executing this code

Loading Library Native
Loading success
Enter a number to get cube: 4
Exception in thread "main" java.lang.UnsatisfiedLinkError: javaapplication2.Native.cubecal(I)I
    at javaapplication2.Native.cubecal(Native Method)
    at javaapplication2.NativeTest.main(NativeTest.java:28)
C:\Users\Chirag\AppData\Local\NetBeans\Cache\8.2\executor-snippets\run.xml:53: Java returned: 1

I know this can be achieved easily by only java code but I am trying native methods so that I can also use the benefits of C++ in my other java projects.

Note: I added all relatives path to Project properties in Visual Studio 2012 follows C:\Program Files\Java\jdk1.8.0_144\include and C:\Program Files\Java\jdk1.8.0_144\include\win32

I also readed these articles Working with java's native method and Java programming with JNI but always ended up with this error.

Please help and also explain me what this exception is about.

Thank you :)

Upvotes: 2

Views: 385

Answers (1)

Chirag
Chirag

Reputation: 565

Yes! finally I got answer after too much of testing. The full code is inside a package, the problem in above snippets is I am not considering the package for creating the header file.. (hehehe... my mistake. sorry for that)

Updated Code snips are:

NativeTest.java

package javaapplication2;

import java.io.File;
import java.util.Scanner;

/**
 *
 * @author Chirag
 */
public class NativeTest {

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        System.out.println("Loading library NativeCube");
        try {
            NativeCube n = new NativeCube();
            System.out.println("Loading Library NativeCube succeeded");
            System.out.print("Enter a number to get cube: ");
            int x = sc.nextInt();
            System.out.println(x + " * " + x + " * " + x + " = " + n.cubecal(x));
        } catch (Throwable e) {
            System.err.println("Error loading library nativeLib: " + e);
            e.printStackTrace();
        }
    }

}

class NativeCube {

    public NativeCube() {
        System.setProperty("java.library.path", new File("").getAbsolutePath());
        System.out.println("Pathes: " + System.getProperty("java.library.path"));
        String arch = System.getProperty("sun.cpu.isalist");
        if (arch.trim().equalsIgnoreCase("amd64")) {
            System.loadLibrary("NativeCube");
        } else {
            System.loadLibrary("NativeCube_x86");
        }
    }

    public native int cubecal(int x);

}

Created header file by javah javaapplication2.NativeCube

javaapplication2_NativeCube.h

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

#ifndef _Included_javaapplication2_NativeCube
#define _Included_javaapplication2_NativeCube
#ifdef __cplusplus
extern "C" {
#endif
    /*
    * Class:     javaapplication2_NativeCube
    * Method:    cubecal
    * Signature: (I)I
    */
    JNIEXPORT jint JNICALL Java_javaapplication2_NativeCube_cubecal
        (JNIEnv *, jobject, jint);

#ifdef __cplusplus
}
#endif
#endif

Main.cpp

#include "javaapplication2_NativeCube.h"

JNIEXPORT jint JNICALL Java_javaapplication2_NativeCube_cubecal
    (JNIEnv *env, jobject obj, jint val){
        return val * val * val;
}

and the output of the program is

Loading library NativeCube
Pathes: C:\Users\Chirag\Documents\NetBeansProjects\JavaApplication2
Loading Library NativeCube succeeded
Enter a number to get cube: 12
12 * 12 * 12 = 1728

Learned a good chapter about not to skip the package name to create the header files.

Thanks @Andrew S and @Sergey for quick response. :)

Upvotes: 1

Related Questions