导航:首页 > 编程语言 > javajni教程

javajni教程

发布时间:2022-05-02 01:58:28

㈠ 浅谈如何用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

㈡ 如何从C中调用Java函数使用JNI

1. 编写并编译J2C.java
import java.lang.management.ManagementFactory;

import java.lang.management.RuntimeMXBean;
public class J2C
{
static
{
try{
// 此处即为本地方法所在链接库名
System.loadLibrary("j2c");
} catch(UnsatisfiedLinkError e)
{
System.err.println( "Cannot load J2C library:\n " +
e.toString() );
}
}
//声明的本地方法
public static native int write2proc(int pid);
public static void main(String[] args){
//获取本进程(即主线程)的pid
final RuntimeMXBean runtime = ManagementFactory.getRuntimeMXBean();
final String info = runtime.getName();
final int index = info.indexOf("@");

if (index != -1) {
final int pid = Integer.parseInt(info.substring(0, index));
System.out.println(info);
System.out.println(pid);
write2proc(pid);
}

try{
Thread.sleep(8000);
} catch(InterruptedException e){
e.printStackTrace();
}
}
}

note:Java程序中System.loadLibrary参数名表示要载入的C/C++共享库,第6步生成的共享库名必须与该参数一致,即System.loadLibrary(Name) 对应共享库名libName.so (共享库名必须以lib开头)
2. 生成C头文件J2C.h:javah J2C
/* DO NOT EDIT THIS FILE - it is machine generated */

#include <jni.h>
/* Header for class J2C */

#ifndef _Included_J2C
#define _Included_J2C
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: J2C
* Method: write2proc
* Signature: (I)I
*/
JNIEXPORT jint JNICALL Java_J2C_write2proc
(JNIEnv *, jclass, jint);
#ifdef __cplusplus
}
#endif
#endif

note:1. 头文件自动生成,不要修改它;
2. 函数JNIEXPORT jint JNICALL Java_J2C_write2proc(JNIEnv *, jclass, jint);
按照注释的说明是在J2C.java文件的类J2C的方法write2proc处定义,故C程序的实现函数必须与该处签名一致;
3. 编写C程序J2C.c
#include <stdio.h>

#include "J2C.h"
JNIEXPORT int JNICALL Java_J2C_write2proc(JNIEnv * env, jobject arg, jint pid)
{
printf("current pid is %d\n", pid);
return 0;
}

4. 编译C程序

因为C程序里#include "J2C.h"而J2C.h又#include <jni.h>, 而gcc里面默认环境并不知道jni.h是什么东西,故编译时需要告诉编译器jni.h的位置( jni.h在jdk 的$JAVA_HOME/include下面),所以才有了上面的编译参数;
因为使用gcc编译得到动态库,在jni调用的时候,某些情况会有异常, 可尝试改用g++。
总结
1. Java中方法的原型声明与C/C++对应的实现文件定义必须一致(可以通过自动生成的C/C++头文件来比较),尤其是类名和方法名;
2. Java中System.loadLibrary()载入的共享库名必须与后面C/C++生成的共享库名一致。

㈢ 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里的native方法怎么运行

你先写个native方法的申明在你的类,如
class MyClass{
public native void sayHello();
}
然后javac编译,
再javah -jni (你的java源文件路径)
它会知道生成一个c的头文件,再在vc(或者vs)新建一个动态链接库(dll)工程,include,再实现你的函数,编译出dll文件,设定一下classpath,让jvm找得到dll,java运行就行了

㈤ JAVA 里面如何 使用jni 给个例子 加 解释。谢谢

JAVA以其跨平台的特性深受人们喜爱,而又正由于它的跨平台的目的,使得它和本地机器的各种内部联系变得很少,约束了它的功能。解决JAVA对本地操作的一种方法就是JNI。
JAVA通过JNI调用本地方法,而本地方法是以库文件的形式存放的(在WINDOWS平台上是DLL文件形式,在UNIX机器上是SO文件形式)。通过调用本地的库文件的内部方法,使JAVA可以实现和本地机器的紧密联系,调用系统级的各接口方法。
简单介绍及应用如下:
一、JAVA中所需要做的工作
在JAVA程序中,首先需要在类中声明所调用的库名称,如下:
static {
System.loadLibrary(“goodluck”);
}

在这里,库的扩展名字可以不用写出来,究竟是DLL还是SO,由系统自己判断。
还需要对将要调用的方法做本地声明,关键字为native。并且只需要声明,而不需要具 体实现。如下:
public native static void set(int i);
public native static int get();
然后编译该JAVA程序文件,生成CLASS,再用JAVAH命令,JNI就会生成C/C++的头文件。
例如程序testdll.java,内容为:
public class testdll
{
static
{
System.loadLibrary("goodluck");
}
public native static int get();
public native static void set(int i);
public static void main(String[] args)
{
testdll test = new testdll();
test.set(10);
System.out.println(test.get());
}
}

用javac testdll.java编译它,会生成testdll.class。
再用javah testdll,则会在当前目录下生成testdll.h文件,这个文件需要被C/C++程序调用来生成所需的库文件。
二、C/C++中所需要做的工作
对于已生成的.h头文件,C/C++所需要做的,就是把它的各个方法具体的实现。然后编译连接成库文件即可。再把库文件拷贝到JAVA程序的路径下面,就可以用JAVA调用C/C++所实现的功能了。
接上例子。我们先看一下testdll.h文件的内容:
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class testdll */
#ifndef _Included_testdll
#define _Included_testdll
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: testdll
* Method: get
* Signature: ()I
*/
JNIEXPORT jint JNICALL Java_testdll_get (JNIEnv *, jclass);
/*
* Class: testdll
* Method: set
* Signature: (I)V
*/
JNIEXPORT void JNICALL Java_testdll_set (JNIEnv *, jclass, jint);
#ifdef __cplusplus
}
#endif
#endif
在具体实现的时候,我们只关心两个函数原型
JNIEXPORT jint JNICALL Java_testdll_get (JNIEnv *, jclass); 和
JNIEXPORT void JNICALL Java_testdll_set (JNIEnv *, jclass, jint);
这里JNIEXPORT和JNICALL都是JNI的关键字,表示此函数是要被JNI调用的。而jint是以JNI为中介使JAVA的int类型与本地的int沟通的一种类型,我们可以视而不见,就当做int使用。函数的名称是JAVA_再加上java程序的package路径再加函数名组成的。参数中,我们也只需要关心在JAVA程序中存在的参数,至于JNIEnv*和jclass我们一般没有必要去碰它。
好,下面我们用testdll.cpp文件具体实现这两个函数:
#include "testdll.h"
int i = 0;
JNIEXPORT jint JNICALL Java_testdll_get (JNIEnv *, jclass)
{
return i;
}
JNIEXPORT void JNICALL Java_testdll_set (JNIEnv *, jclass, jint j)
{
i = j;
}
编译连接成库文件,本例是在WINDOWS下做的,生成的是DLL文件。并且名称要与JAVA中需要调用的一致,这里就是goodluck.dll 。把goodluck.dll拷贝到testdll.class的目录下,java testdll运行它,就可以观察到结果了。

㈥ java jni 怎么在windows环境中编译成linux下的so文件

可以直接在android工程下使用,因为android就是linux内核。

㈦ 如何用JNI技术提高Java的性能详解

阻碍Java取得广泛使用的一个首要因素是Java程序的运行效率。Java是介于解释型和编译型之间的一种语言,同样的程序,假如用编译型语言C来实现,其运行速度通常要比Java快一倍以上。Java具有平台无关性,这使人们在开发企业级使用的时刻总是把它作为首要候选方案之一,但是性能方面的因素又大大削弱了它的竞争力。为此,提高Java的性能就显得十分主要。 疑问的提出 Sun公司及Java的支撑者们为提高Java的运行速度已经做出了许多全力,其中大多数集中在程序设计的要领和模式挑选方面。由于算法和设计模式的优化是通用的,对Java有效的优化算法和设计模式,对其他编译语言也基本同样适用,因此无法从根本上改动 Java程序与编译型语言在执行效率方面的差别。 JIT(Just In Time,及时编译)技能是个比较好的思想。它的基本原理是:最先议决 Java编译器把Java源代码编译成平台无关的二进制字节码。然后在Java程序真实执行之前,系统议决 JIT编译器把Java的字节码编译为本地化机器码。结尾,系统执行本地化机器码,节省了对字节码实行解释的时间。这样做的优点是大大提高了Java程序的性能,缩短了加载程序的时间;同时,由于编译的结果并不在程序运行间保存,因此也节约了存储空间。缺点是由于JIT编译器对所有的代码都想优化,因此同样也占用了许多时间。 动态优化技能是提高Java性能的另一个尝试。该技能试图议决把Java源程序直接编译成机器码,以充分使用 Java动态编译和静态编译技能来提高Java的性能。该要领把输入的Java源码或字节码转换为经历高度优化的可执行代码和动态库 (Windows中的. dll文件或Unix中的. so文件)。该技能能大大提高程序的性能,但却破坏了Java的可移植性。 JNI技能 实际上,有一种通常为咱们忽视的技能能够在很大程度上处理这个难题,那就是JNI(Java Native Interface, Java本地化要领 )。主张采用纯Java的人们通常反对本地化代码的运用,他们认为在Java程序执行的流程中调用C/C++程序会影响程序的可移植性和安全性。还有一些人认为JNI只是对过去混合编程技能的基本扩展,本来际目标是为了充分使用大量原有的C程序库。 本来,咱们不必拘泥于严格的平台独立性限定,因为采用JNI技能只是针对一些严重影响Java性能的代码段,该部分可能只占源程序的极少部分,所以几乎能够不思虑该部分代码在主流平台之间移植的工作量。同时,也不必过分担心类型匹配疑问,咱们完全能够控制代码不出现这种不正确。此外,也不必担心安全控制疑问,因为Java安全模型已扩展为准许非系统类加载和调用本地点法。根据Java规范,从JDK 1. 2开始,FindClass将设法找到与当前的本地点法关联的类加载器。假如平台有关代码属于一个系统类,则无需涉及任何类加载器; 否则,将调用适当的类加载器来加载和链接已命名的类。换句话说,假如在Java程序中直接调用C/C++语言产生的机器码,该部分代码的安全性就由Java虚拟机控制。

㈧ 怎么用jni

·编写带有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. include2. includeJNIEXPORT 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!!!”在首次使用JNI的时候有些疑问,后来在使用中一一解决,下面就是这些问题的备忘:1。 java和c是如何互通的?其实不能互通的原因主要是数据类型的问题,jni解决了这个问题,例如那个c文件中的jstring数据类型就是java传入的String对象,经过jni函数的转化就能成为c的char*。对应数据类型关系如下表:Java 类型 本地c类型 说明 boolean jboolean 无符号,8 位 byte jbyte 无符号,8 位 char jchar 无符号,16 位 short jshort 有符号,16 位 int jint 有符号,32 位 long jlong 有符号,64 位 float jfloat 32 位 double jdouble 64 位 void void N/AJNI 还包含了很多对应于不同 Java 对象的引用类型如下图:2. 如何将java传入的String参数转换为c的char*,然后使用?java传入的String参数,在c文件中被jni转换为jstring的数据类型,在c文件中声明char* test,然后test = (char*)(*env)->GetStringUTFChars(env, jstring, NULL);注意:test使用完后,通知虚拟机平台相关代码无需再访问:(*env)->ReleaseStringUTFChars(env, jstring, test);3. 将c中获取的一个char*的buffer传递给java?这个char*如果是一般的字符串的话,作为string传回去就可以了。如果是含有’\0’的buffer,最好作为bytearray传出,因为可以制定的length,如果到string,可能到’\0’就截断了。有两种方式传递得到的数据:一种是在jni中直接new一个byte数组,然后调用函数(*env)->SetByteArrayRegion(env, bytearray, 0, len, buffer);将buffer的值到bytearray中,函数直接return bytearray就可以了。一种是return错误号,数据作为参数传出,但是java的基本数据类型是传值,对象是传递的引用,所以将这个需要传出的byte数组用某个类包一下,如下:class RetObj { public byte[] bytearray; } 这个对象作为函数的参数retobj传出,通过如下函数将retobj中的byte数组赋值便于传出。代码如下: jclass cls; jfieldID fid; jbyteArray bytearray; bytearray = (*env)->NewByteArray(env,len); (*env)->SetByteArrayRegion(env, bytearray, 0, len, buffer); cls = (*env)->GetObjectClass(env, retobj); fid = (*env)->GetFieldID(env, cls, "retbytes", "[B"]); (*env)->SetObjectField(env, retobj, fid, bytearray);4. 不知道占用多少空间的buffer,如何传递出去呢?在jni的c文件中new出空间,传递出去。java的数据不初始化,指向传递出去的空间即可。 你还费解吗</SPAN></SPAN></SPAN></SPAN>
</p>

㈨ linux中在java声明了一个string在jni端怎么调用

1.自己写.c文件,然后生成so库2.引用别人的静态库,或者动态库来生成新的jni调用库。我们先来看最简单的编写一个jni调用的so库,包含一个获取字符串的方法,通过这个列子,我们主要是了解怎么在android的工程中调用jni的库,以及要注意的问题。第一步:首先我们来看下我们的工程的目录jni目录是我们生成库的文件,里面包含了一个.mk编译文件以及一系列的.c文件libs目录是我们编译jni目录下的mk文件动态生成的。当我们写好了jni下面的库文件以后,在当前目录下执行ndk-build则会自动生成我们需要调用的.so库文件。第二步:java里面怎么调用jni的库文件,我们先看代码{/**'hello-jni'nativelibrary,whichispackaged*withthisapplication.*/();/*thisisusedtoloadthe'hello-jni'libraryonapplication*startup.*/data/data/com.example.HelloJni/lib/libhello-jni.soat*.*/static{System.loadLibrary("hello-jni");}@OverridepublicvoidonCreate(BundlesavedInstanceState){super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);Stringstr=stringFromJNI();System.out.println("*****str:"+str);}}在java文件中要做到调用jni文件生成的so库,需要做到2步

阅读全文

与javajni教程相关的资料

热点内容
职业生涯pdf 浏览:953
ubuntu安装软件php 浏览:159
黑马程序员退学流程 浏览:362
网页服务器崩溃怎么回事 浏览:651
cnc编程前景怎么样 浏览:319
lniux命令详解 浏览:493
linuxmysql查询日志 浏览:368
老捷达伙伴压缩比 浏览:93
改后缀加密 浏览:433
邮局选址问题算法 浏览:14
河北服务器内存云主机 浏览:12
在电脑上怎么找到加密狗图标 浏览:435
电脑的浏览器怎么打开pdf文件怎么打开 浏览:142
pdf卡片库下载 浏览:11
单片机中二进制表示什么 浏览:725
java网络编程推荐 浏览:795
施耐德开关编程 浏览:66
组织胚胎学pdf 浏览:844
linux查看发包 浏览:496
加密货币交易所暴利时代 浏览:824