AFTER EDIT
I get the this error
1> Creating library D:\Jni tester\Debug\Jni tester.lib and object D:\Jni tester\Debug\Jni tester.exp
1>MSVCRTD.lib(crtexe.obj) : error LNK2019: unresolved external symbol _main referenced in function ___tmainCRTStartup
1>D:\Jni tester\Debug\Jni tester.exe : fatal error LNK1120: 1 unresolved externals
when i run the following code :
#include <jni.h>
#include <stdio.h>
#include "HelloWorld.h"
JNIEXPORT void JNICALL
Java_HelloWorld_print( JNIEnv *env , jobject obj) {
printf("Hello World!\n");
return;
}
This is the header file HelloWorld.h
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class HelloWorld */
#ifndef _Included_HelloWorld
#define _Included_HelloWorld
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: HelloWorld
* Method: print
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_HelloWorld_print
(JNIEnv *, jobject);
#ifdef __cplusplus
}
#endif
#endif
Why do i get this error ?
JNIENv should be JNIEnv (lower case n) as shown by this Getting Started guide.
Edit: As seems from your error, you should define the project as a DLL, in your case it looks for the main method since it tries to create an executable.
Related
I have those two super basic methods in Java like so:
package com.lisek;
class HelloWorldJNI {
static {
System.loadLibrary("native");
}
public static void main(String[] args) {
HelloWorldJNI helloWorldJNI = new HelloWorldJNI();
helloWorldJNI.sayHello();
helloWorldJNI.sayHello2();
}
// Declare a native method sayHello() that receives no arguments and returns void
private native void sayHello();
private native void sayHello2();
}
I am generating JNI files like so javac -h . HelloWorldJNI.java which results in such com_lisek_HelloWorldJNI.h file:
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_lisek_HelloWorldJNI */
#ifndef _Included_com_lisek_HelloWorldJNI
#define _Included_com_lisek_HelloWorldJNI
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_lisek_HelloWorldJNI
* Method: sayHello
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_com_lisek_HelloWorldJNI_sayHello
(JNIEnv *, jobject);
/*
* Class: com_lisek_HelloWorldJNI
* Method: sayHello2
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_com_lisek_HelloWorldJNI_sayHello2
(JNIEnv *, jobject);
#ifdef __cplusplus
}
#endif
#endif
And I am doing implementation of those in the same exact manner in the com_lisek_HelloWorldJNI.cpp file like so:
#include "com_lisek_HelloWorldJNI.h"
#include <stdio.h>
#include <iostream>
#include <jni.h>
JNIEXPORT void JNICALL Java_com_lisek_HelloWorldJNI_sayHello (JNIEnv* env, jobject thisObject) {
std::cout << "Hello from C++ !!" << std::endl;
}
JNIEXPORT void JNICALL Java_com_lisek_HelloWorldJNI_sayHello2 (JNIEnv* env, jobject thisObject) {
std::cout << "Hello from C++ !!" << std::endl;
}
I am compiling the code with g++ -c -I"C:\Program Files\Java\jdk1.8.0_181\include" -I"C:\Program Files\Java\jdk1.8.0_181\include\win32" com_lisek_HelloWorldJNI.cpp -o com_lisek_HelloWorldJNI.o and generating .dll with g++ -shared -o native.dll com_lisek_HelloWorldJNI.o -Wl,--add-stdcall-alias. All looks very well to me and I can not spot any flaw of this code but nevertheless in Java while running the code I am getting exception only on the second method:
Hello from C++ !!
Exception in thread "main" java.lang.UnsatisfiedLinkError: com.lisek.HelloWorldJNI.sayHello2()V
at com.lisek.HelloWorldJNI.sayHello2(Native Method)
at com.lisek.HelloWorldJNI.main(HelloWorldJNI.java:12)
It means to me that the .dll is loaded properly as if I do two calls of the sayHello() I will get the Hello twice. Seriously, what is going on?
Remember to compile and run your code with -Djava.library.path flag set like so:
java -cp . -Djava.library.path="D:\\Workspace\\JNI\\Callback\\src\\com\\lisek" com.lisek.HelloWorldJNI
But it still dazzles me that it was able to run the first sayHello() but was not able to run sayHello2(). Can't think of any reasonable idea why this happens.
If you are doing example from https://www.baeldung.com/jni then make sure that you add these includes into cpp file
#include <jni.h>
#include <iostream>
#include "Main.h"
My JNI was working fine as far as i remember a couple of days. Now i am getting the error:
DODJNI.h:15: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘void’
However this is the machine created header file and so presumly there should be no errors with the header file, as it says at the top to not modify it
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class DoDJNI */
#ifndef _Included_DoDJNI
#define _Included_DoDJNI
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: DoDJNI
* Method: parseCommand
* Signature: (Ljava/lang/String;)V
*/
JNIEXPORT void JNICALL Java_DoDJNI_parseCommand
(JNIEnv *, jobject, jstring);
#ifdef __cplusplus
}
#endif
#endif
I am trying to link a Java swing frontend to the c++ backend using JNI. I am able to generate a class file and header file for that class. I could also write the .cpp file and also generate a library file. But when I try to run my application I get an error undefined symbol: __gxx_personality_v0.
I went through many examples on stackoverflow but none of it worked in my case. I made sure I have libgcc, libgcj and libstd++. Also added pragma GCC java_exceptions on the top of the JNI header file.
But none of these worked.
Java file - InitJNI.java
public class InitJNI {
public native String callMethod(String str);
public static void init(String s){
System.out.println("-------inside InitJNI.java--------");
System.loadLibrary("eg1");
System.out.println("Library loaded in InitJNI--------");
InitJNI init1 = new InitJNI();
init1.callMethod(s);
}
}
JNI header file - InitJNI.h
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class org_openscience_jchempaint_application_InitJNI */
#ifndef _Included_InitJNI
#define _Included_InitJNI
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: InitJNI
* Method: callMethod
* Signature: (Ljava/lang/String;)Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_InitJNI_callMethod
(JNIEnv *, jobject, jstring);
#ifdef __cplusplus
}
#endif
#endif
Cpp file - InitJNI.cpp
#include "InitJNI.h"
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#pragma GCC java_exceptions
JNIEXPORT jstring JNICALL Java_InitJNI_callMethod
(JNIEnv * env, jobject, jstring string){
char buf[128];
const char *str = env->GetStringUTFChars(string, NULL);
printf("%s", str);
env->ReleaseStringUTFChars(string, str);
}
I am trying to create a shared lib using command:
g++ -shared -fpic -o libeg1.so -I/usr/java/include -I/usr/java/include/linux InitJNI.cpp
Which generates libeg1.so file. But my application does not run. It gives me
undefined symbol: __gxx_personality_v0
Any help with this is appreciated.
Thank you!
I know this is an often-seen problem and after search on the web, problem still not solved. -Djava.library.path is already added to the command.
Here is my java file
public class TestJni
{
public native void print(A a);
static{
System.loadLibrary("MyJni");
}
public static void main(String []args){
new TestJni().print(new A());
}
}
class A{
void show(){
System.out.println("In a show function");
}
}
I am trying to create an instance 'a' which is A class.
Pass it to native method print and let native method to invoke show() method.
Compile .java into .class
javac TestJni.java
Now I have three files: A.class TestJni.class TestJni.java
Use
javah -classpath . TestJni
to get .h file which is like:
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class TestJni */
#ifndef _Included_TestJni
#define _Included_TestJni
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: TestJni
* Method: print
* Signature: (LA;)V
*/
JNIEXPORT void JNICALL Java_TestJni_print
(JNIEnv *, jobject, jobject);
#ifdef __cplusplus
}
#endif
#endif
Rename it to MyJni.h by
mv TestJni.h MyJni.h
Create MyJni.c by
vim MyJni.c
the content of MyJni.c is:
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
#include "MyJni.h"
/* Header for class TestJni */
#ifndef _Included_TestJni
#define _Included_TestJni
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: TestJni
* Method: print
* Signature: (LA;)V
*/
JNIEXPORT void JNICALL Java_TestJni_print
(JNIEnv *env, jobject obj, jobject o){
jclass cls = (*env)->GetObjectClass(env, o);
jmethodID mid = (*env)->GetMethodID(env, cls, "show", "()V");
(*env)->CallVoidMethod(env, o, mid);
}
#ifdef __cplusplus
}
#endif
#endif
Build .so file by
gcc -fPIC -shared -o libMyJni.so MyJni.c -I. -I$JAVA_HOME/include -I$JAVA_HOME/include/linux
And now I have 5 files [A.class libMyJni.so MyJni.c MyJni.h TestJni.class TestJni.java] in my directory: /home/grid/code/tmp
Run java program:
java -cp . -Djava.library.path=. TestJni
Now I get the Error which is
Exception in thread "main" java.lang.UnsatisfiedLinkError: TestJni.print(LA;)V
at TestJni.print(Native Method)
at TestJni.main(TestJni.java:10)
I am coding under Ubuntu 14.10 and gcc program is the default one.
I really not able to figure out what is wrong.
Please help me to correct the program.
Thank you very much in advance!!!
Remove the
#ifndef _Included_TestJni
#define _Included_TestJni
...
#endif
from the source file. You've already #defined the include guard in the header, so this effectively comments out the code.
Remove the #include "MyJni.h" or
#ifndef _Included_TestJni
#define _Included_TestJni
//..
#endif
Exception in thread "main" java.lang.UnsatisfiedLinkError: TestJni.print(LA;)V this usually happen when JNI can't find the symbol definition in your library. You can use nm to analyze the JNI function you call to see if it is defined and exported in your library.
$ nm libMyJni.so
00000000000005ac T Java_TestJni_print
0000000000200e40 a _DYNAMIC
0000000000200fe8 a _GLOBAL_OFFSET_TABLE_
w _Jv_RegisterClasses
0000000000200e20 d __CTOR_END__
0000000000200e18 d __CTOR_LIST__
You can try using System.load. iirc System.loadLibrary loads .so/.dll files from the default location. System.load should work with an absolute path to the .so/.dll file.
I had a previously working JNI lib,
for some reason (I am not aware of any curcial changes) I can't use it anymore, as I get the following error:
Exception in thread "main" java.lang.UnsatisfiedLinkError: de.ifi.lmu.sommerd.ftsserver.jni.IndexJNI.loadIndex(Ljava/lang/String;)V
at de.ifi.lmu.sommerd.ftsserver.jni.IndexJNI.loadIndex(Native Method)
So here is my test setup:
package de.ifi.lmu.sommerd.ftsserver.jni;
public class IndexJNI {
static {
System.load("/home/XXX/workspace/IndexJNI/resources/newLib.so");
System.out.println("Loading library worked");
IndexJNI.loadIndex("");
}
public static native void loadIndex(String indexName);
}
And here the relevant parts of the .h and .c files:
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class de_ifi_lmu_sommerd_ftsserver_jni_IndexJNI */
#ifndef _Included_de_ifi_lmu_sommerd_ftsserver_jni_IndexJNI
#define _Included_de_ifi_lmu_sommerd_ftsserver_jni_IndexJNI
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: de_ifi_lmu_sommerd_ftsserver_jni_IndexJNI
* Method: loadIndex
* Signature: (Ljava/lang/String;)V
*/
JNIEXPORT void JNICALL Java_de_ifi_lmu_sommerd_ftsserver_jni_IndexJNI_loadIndex
(JNIEnv *, jobject, jstring);
#ifdef __cplusplus
}
#endif
#endif
The .c file
JNIEXPORT void JNICALL Java_de_ifi_lmu_sommerd_ftsserver_jni_IndexJNI_loadIndex
(JNIEnv * env, jclass jc, jstring indexName) {
...
}
And this is my makefile:
test_gcc_lib: run_queries.o
g++ -shared -fPIC run_queries.o SSA.a -o newLib.so
So the problem was that I had changed the call to static,
so now the signature was not correct anymore.
I just had to change jobject to jclass.