javajni调用
㈠ java调用openssl的dll,用jni如何调用
jna去调用,只需要申明接口就行了, 非常简单
㈡ java通过jni怎么调用c
只提供思路,自己去摸索,这样才能吧知识转化为自己的
1、编译一个class类 里面定义一个函数,注意要用native关键字,这是 jni入口的标志
比如 public int native jniSum(int a, int b) ;
不需要实现这个函数,像定义接口一样。
2、使用jdk里面的一个工具 exe,叫什么 jnih.exe 忘了。敲命令通过这个class 生成一个同名的 .h 文件 .h 里面会包含包路径的。
3、然后你就可以自己写 C/C++代码,实现 .h里 生成的 jniSum的 C版本的函数了
4,然后将这个C/C++的代码编译生成一个 dll 比如名字叫 LibJniSum.dll
5,在你的 class类里,加入静态引用
static {
System.loadLibrary("LibJniSum") ;//不要 后缀。
}
只要程序找得到你的 dll,就会自动加载dll
然后你就可以直接调用你的 jniSum了
㈢ 如何通过JNI在Java中调用C库函数
要在java中调用c语言的库,需要使用Java提供了JNI。
举例说明
在c语言中定义一个 void sayHello()函数(打印Hello World);然后在Java中调用这个函数显示Hello Word.
现在分别从Java和C语言两部分说明:
1. Java 部分
首先定义一个HelloNative,在其中申明sayHello函数,函数要申明为Native 类型的.如下:
public class HelloNative {
public native void sayHello();
}
编译这个类,生成class文件:
javac HelloWorld.java
利用javah生成需要的h文件
javah HelloNative
生成的 h文件大概如下:
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class HelloNative */
#ifndef _Included_HelloNative
#define _Included_HelloNative
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: HelloNative
* Method: sayHello
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_HelloNative_sayHello
(JNIEnv *, jobject);
#ifdef __cplusplus
}
#endif
#endif
可以看一下上面自动生成的程序,程序include了jni.h,这个头文件在 $JAVA_HOME下的include文件夹下. 还可以发现生成的函数名是在之前的函数名前面加上了Java_HelloNative。
2. C语言部分
根据上面生成的h文件编写相应的代码实现,建立一个 HelloNative.cpp用来实现显示Hello World的函数.如下:
#include <stdio.h>
#include "HelloNative.h"
JNIEXPORT void JNICALL Java_HelloNative_sayHello(JNIEnv *, jobject)
{
printf("Hello World!\n");
}
代码编写完成之后,我们再用gcc编译成库文件,命令如下;
gcc -fPIC -I/usr/lib/jvm/java-7-openjdk-i386/include -I/usr/lib/jvm/java-7-openjdk-i386/include/linux -shared -o libHelloNative.so HelloNative.cpp
这样就会在当前目录下生成一个libHelloNative.so的库文件.这时需要的库已经生成,在C语言下的工作已经完成了.
接下来需要在Java中编写一个程序测试一下.在程序前,需要将我们的库载入进去.载入的方法是调用Java的 System.loadLibrary("HelloNative");
public class TestNative
{
static {
try {
System.loadLibrary("HelloNative");
}
catch(UnsatisfiedLinkError e) {
System.out.println( "Cannot load hello library:\n " + e.toString() );
}
}
public static void main(String[] args) {
HelloNative test = new HelloNative();
test.sayHello();
}
}
但是再编译后,运行的时候,问题又出现了.
Cannot load hello library:
java.lang.UnsatisfiedLinkError: no HelloNative in java.library.path
Exception in thread "main" java.lang.UnsatisfiedLinkError: HelloNative.sayHello()V
at HelloNative.sayHello(Native Method)
at TestNative.main(TestNative.java:13)
载入库失败,但是库明明就是放在当前文件夹下的,怎么会载入失败呢?
用System.getProperty("java.library.path")查看,发现java.library.path中并不u存在当前的目录.主要有以下的几个解决办法:
1) 将生成的库复制到java.library.path有的路径中去,当然这样不是很好
2) 设置环境变量export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH ,将当前的目录加入到LD_LIBRARY_PATH中
3) 设置java 的选项,将当前的目录加入到其中 .java -Djava.library.path=. $LD_LIBRARY_PATH
这样之后程序就能够成功的运行了.可以看见显示的"Hello World!"了
㈣ 在JAVA中用JNI调用C++程序报错,说找不到所依赖的库。
pfjni.dll这个是在你的java工程项目下
还是你的java工程项目下的dll在引用这个dll而找不到这个dll
㈤ jni调用 java和c是同个线程吗
是的,jni调用时, java和c是同个线程。
检测方法:在java和c中分别把当前线程的id输出出来查看。
Java获取线程Id:
Thread.currentThread().getId();
C中获取线程Id:
GetCurrentThreadId();
㈥ 如何从使用 JNI Java 调用本机 代码
JNI是Java Native Interface的缩写,中文为JAVA本地调用。从Java 1.1 开始,Java Native Interface (JNI)标准成为java平台的一部分,它允许Java代码和其他语言写的代码进行交互。JNI一开始是为了本地已编译语言,尤其是C和C++而设计的,但是它并不妨碍你使用其他语言,只要调用约定受支持就可以了。
使用java与本地已编译的代码交互,通常会丧失平台可移植性。但是,有些情况下这样做是可以接受的,甚至是必须的,比如,使用一些旧的库,与硬件、操作系统进行交互,或者为了提高程序的性能。JNI标准至少保证本地代码能工作在任何Java 虚拟机实现下。
------------------------------------------------------------------
编写带有native声明的方法的java类
·使用javac命令编译所编写的java类
·使用javah ?jni java类名生成扩展名为h的头文件
·使用C/C++实现本地方法
·将C/C++编写的文件生成动态连接库
·ok
1) 编写java程序:这里以HelloWorld为例。
代码1:
class HelloWorld {
public native void displayHelloWorld();
static {
System.loadLibrary("hello");
}
public static void main(String[] args) {
new HelloWorld().displayHelloWorld();
}
}
声明native方法:如果你想将一个方法做为一个本地方法的话,那么你就必须声明改方法为 native的,并且不能实现。其中方法的参数和返回值在后面讲述。 Load动态库:System.loadLibrary("hello");加载动态库(我们可以这样理解:我们的方法 displayHelloWorld()没有实现,但是我们在下面就直接使用了,所以必须在使用之前对它进行初始化)这里一般是以static块进行加载的。同时需要注意的是System.loadLibrary();的参数“hello”是动态库的名字。
2) 编译
没有什么好说的了 javac HelloWorld.java
3) 生成扩展名为h的头文件 javah ?
jni HelloWorld 头文件的内容: /* DO NOT EDIT THIS FILE - it is machine generated */
1. include
/* Header for class HelloWorld */
1. ifndef _Included_HelloWorld
2. define _Included_HelloWorld
3. ifdef __cplusplus
extern "C" {
1. endif
/*
* Class: HelloWorld
* Method: displayHelloWorld
* Signature: ()V
* /
JNIEXPORT void JNICALL Java_HelloWorld_displayHelloWorld (JNIEnv *, jobject);
1. ifdef __cplusplus
}
1. endif
2. endif
(这里我们可以这样理解:这个h文件相当于我们在java里面的接口,这里声明了一个 Java_HelloWorld_displayHelloWorld (JNIEnv *, jobject);方法,然后在我们的本地方法里面实现这个方法,也就是说我们在编写C/C++程序的时候所使用的方法名必须和这里的一致)。
4) 编写本地方法实现和由javah命令生成的头文件里面声明的方法名相同的方法。
代码2:
1 #include "jni.h"
2 #include "HelloWorld.h"
3 //#include other headers
4 JNIEXPORT void JNICALL Java_HelloWorld_displayHelloWorld(JNIEnv *env, jobject obj)
{
printf("Hello world!\n");
return;
}
注意代码2中的第1行,需要将jni.h(该文件可以在%JAVA_HOME%/include文件夹下面找到)文件引入,因为在程序中的JNIEnv、 jobject等类型都是在该头文件中定义的;另外在第2行需要将HelloWorld.h头文件引入(我是这么理解的:相当于我们在编写java程序的时候,实现一个接口的话需要声明才可以,这里就是将HelloWorld.h头文件里面声明的方法加以实现。当然不一定是这样)。然后保存为 HelloWorldImpl.c就ok了。
5) 生成动态库
这里以在Windows中为例,需要生成dll文件。在保存HelloWorldImpl.c 文件夹下面,使用VC的编译器cl成。 cl -I%java_home%\include -I%java_home%\include\win32 -LD HelloWorldImp.c -Fehello.dll 注意:生成的dll文件名在选项-Fe后面配置,这里是hello,因为在HelloWorld.java文件中我们loadLibary的时候使用的名字是hello。当然这里修改之后那里也需要修改。另外需要将-I%java_home%\include -I%java_home%\include\win32参数加上,因为在第四步里面编写本地方法的时候引入了jni.h文件。
6) 运行程序 java HelloWorld就ok.
---------------------------------------------------------------
下面是一个简单的例子实现打印一句话的功能,但是用的c的printf最终实现。一般提供给java的jni接口包括一个so文件(封装了c函数的实现)和一个java文件(需要调用path的类)。
1. JNI的目的是使java方法中能够调用c实现的一些函数,比如以下的java类,就需要调用一个本地函数testjni(一般声明为private native类型),首先需要创建文件weiqiong.java,内容如下:
class weiqiong { static { System.loadLibrary("testjni");//载入静态库,test函数在其中实现 } private native void testjni(); //声明本地调用 public void test() { testjni(); } public static void main(String args[]) { weiqiong haha = new weiqiong(); haha.test(); } }
2.然后执行javac weiqiong.java,如果没有报错,会生成一个weiqiong.class。
3.然后设置classpath为你当前的工作目录,如直接输入命令行:set classpath = weiqiong.class所在的完整目录(如 c:\test)再执行javah weiqiong,会生成一个文件weiqiong.h文件,其中有一个函数的声明如下:
JNIEXPORT void JNICALL Java_weiqiong_testjni (JNIEnv *, jobject);
4.创建文件testjni.c将上面那个函数实现,内容如下:
1. include
2. include
JNIEXPORT void JNICALL Java_weiqiong_testjni (JNIEnv *env, jobject obj) { printf("haha---------go into c!!!\n"); }
5.为了生成.so文件,创建makefile文件如下:
libtestjni.so:testjni.o makefile gcc -Wall -rdynamic -shared -o libtestjni.so testjni.o testjni.o:testjni.c weiqiong.h gcc -Wall -c testjni.c -I./ -I/usr/java/j2sdk1.4.0/include -I/usr/java/j2sdk1.4.0/include/linux cl: rm -rf *.o *.so 注意:gcc前面是tab空,j2sdk的目录根据自己装的j2sdk的具体版本来写,生成的so文件的名字必须是loadLibrary的参数名前加 “lib”。
6.export LD_LIBRARY_PATH=.,由此设置library路径为当前目录,这样java文件才能找到so文件。一般的做法是将so文件到本机的LD_LIBRARY_PATH目录下。
7.执行java weiqiong,打印出结果:“haha---------go into c!!!”
㈦ Java通过JNI调用C 传递参数时,想传递地址,怎么实现
java数组传递给jni实际是指针,只是java禁止你直接在jni里对java数组操作,所以在jni需要对java数组转换为jni里可以回操作的数组。典型的答还有字符串,c struct等。
之所以禁止jni直接操作数组可能是jvm在安全等方面的考虑。jni调用涉及到java内存栈和native内存栈。jvm只能处理到java内存,没有实现自动管理jni调用的内存。试想下如果jni里操作java数组刚好被回收了会怎样?
所以在jni里需要拷贝java数组副本,而且分配或者是引用了对象,需要手动释放删除(DeleteLocalRef、ReleaseXX)。jni调用实际是个很大的开销.
㈧ 浅谈如何用JNI的代码调用java接口
对于本地函数
JNIEXPORT void JNICALL Java_video1_TestNative_sayHello(JNIEnv * env, jobject obj)
{
cout<<"Hello Native Test !"<<endl;
}
JNIEnv类型代表Java环境。通过这个JNIEnv*指针,就可以对Java端的代码进行操作专。如,创建属Java类得对象,调用Java对象的方法,获取Java对象的属性等。
JNIEnv的指针会被JNI传送到本地方法的实现函数中来对Java端的代码进行操作
JNIEnv类中的函数:
NewObject/NewString/New<TYPE>Array :new新对象
Get/Set<TYPE>Field:获取属性
Get/SetStatic<TYPE>Field :获取静态属性
Call<TYPE>Method/CallStatic<TYPE>Method
㈨ java 调用动态链接库(jni方式调用dll文件)
jni 是由Java调用C/C++的动态链接库 (DLL)。
所以把.class-->.h-->dll ,想法是不正确的,
同时也违背了Jni的初衷。
Dll是由C/C++生成的。
以前的一个项目用到了Java调用C/C++的DLL,所以对这个还算熟悉。
那个dLL是由C++程序员写的,在Microsoft Visual C++ 6.0编辑器中可以生成。然后由Java程序员用JNI来调用DLL里面实现的功能(方法)。
㈩ java jni 调用 c,如何传递java class 对象
你可以在类里面使用构造方法给成员变量赋值
比如 下面这个类,有get和set方法,可以赋值,可以取值,不知道是否是你需要的
public class EUser
{
private String name;
private int age;
private String gender;
public EUser()
{
}
public EUser(String name, int age, String gender) {
super();
this.name = name;
this.age = age;
this.gender = gender;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
}