Java 调用本地Native接口指引

原创 2016年05月31日 20:00:56

Java本地接口允许java用户用代码与其他语言接口交互的一种方法,native方法允许java语言调用其他语言,增加了代码的灵活性

1、Java本地接口的好处

通过使用Java接口,可以增加代码的灵活性与重用性,假如我们想在java里用一段C语言的代码实现的功能,我们不用全部重写所有C语言代码,而是可以加一个C语言接口类,与java交互即可。
通过java接口,还可以提升java程序的性能瓶颈,我们知道,java在运行的时候由于需要运行在jvm上,因此效率会有所下降,这也是为了跨平台性做了一个折中的办法,通过jni,我们可以将一些代码放在native代码中,通常native代码的速度比java代码快很多,因此可以提升java程序的性能。

2、Java本地方法的开发过程

目的:实现一个Hello类,在Hello类里面定义一个native'的方法,并且这个方法转由C语言实现。

首先,我们创建一个Hello类:
public class Hello {
	public native void sayHi(); //1
    static { System.loadLibrary("hello"); } //2

	public static void main (String[] args) {
	    Hello hello = new Hello();
		System.out.println("I will Print:");
		hello.sayHi();//3
	}
}

其中,第一步创建一个native的sayHi方法,方法的实现并未实现,而是由下面的C语言来实现。
第二步加载C语言库,在windows下,库名为hello.dll,在Linux下,库名为libhello.so,在macos系统下库名为libhello.jnilib
第三步在main方法里面调用我们定义的native方法,来验证我们的方法是否成功执行。

其次,通过javac工具编译这个类:
$ javac Hello.java 

如果是有包的话需要加上包路径名。

然后,用javah工具创建native的.h头文件,这个文件为自动生成
$ javah -jni Hello

创建好之后,我们的文件夹中就多了个Hello.h头文件:
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class Hello */

#ifndef _Included_Hello
#define _Included_Hello
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     Hello
 * Method:    sayHi
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_Hello_sayHi
  (JNIEnv *, jobject);

#ifdef __cplusplus
}
#endif
#endif

这个文件里定义了我们需要实现的函数原型:
JNIEXPORT void JNICALL Java_Hello_sayHi
  (JNIEnv *, jobject);
然后我们需要实现具体的定义,创建一个hello.c文件:
#include<stdio.h>
#include"Hello.h"

JNIEXPORT void JNICALL
Java_Hello_sayHi(JNIEnv *env, jobject obj) {
    printf("Hello World\n");
}

在实现中,我们需要include我们刚才自动创建好的.h文件,并且实现它定义的函数。

然后我们生成.so库文件:
$ gcc -o libhello.so -fPIC -lc -shared -I /usr/lib/jvm/java/include -I /usr/lib/jvm/java/include/linux hello.c
-o为输出文件名,不能随意更改,要以lib+库名(就是java代码里loadLibrary里的字符串)+.so命名
-I 由于需要jni.h和其他的一些头文件,需要加上依赖的头文件路径

然后我们需要把当前文件目录加入库文件路径中:
$ export LD_LIBRARY_PATH=.

ok,至此已经全部完成操作,最后我们java Hello就可以执行代码了。

3、可能出错的地方

常见的错误有两个地方,一个是: java.lang.UnsatisfiedLinkError: no HelloWorld in java.library.path,这个是由于找不到库文件所致的,原因有很多,最常见的是文件名规则设置错误,或者没有export  LD_LIBRARY_PATH使得java找不到库文件。
还有一个错误的是:Exception in thread "main" java.lang.UnsatisfiedLinkError: xxx.xxx.HelloWorld.myprint()V,这个是由于我们的库虽然找到了,但是定义却是错误的,大多数原因是我们自己写的函数名有错误,或者参数有错误所致,仔细检查一遍即可。
版权声明:本文为博主原创文章,未经博主允许不得转载。

java学习(7)native 与C的接口

Java不是完美的,Java的不足除了体现在运行速度上要比传统的C++慢许多之外,Java无法直接访问到操作系统底层(如系统硬件等),为此Java使用native方法来扩展Java程序的功能。  ...

java native 接口开发流程

http://assertmyself.iteye.com/blog/2344026 java native 接口开发流程 1.编写native接口 Hello.java ...

【EJB学习笔记】——远程调用和本地调用

EJB应用可以发布为远程调用和本地调用。 从字面意思来理解,远程调用就是客户端(调用的模块)和服务端(被调用的模块)“不在一起”,“相隔很远”;本地调用就是客户端(调用的模块)和服务端(被调用的模块...

Java调用本地方法又是怎么一回事

JNIJNI即Java Native Interface,它能在Java层实现对本地方法的调用,一般本地的实现语言主要是C/C++,其实从虚拟机层面来看JNI挺好理解,JVM主要使用C/C++ 和少量...

JAVA本地方法

一. 什么是Native Method   简单地讲,一个Native Method就是一个java调用非java代码的接口。一个Native Method是这样一个java的方法:该方法的实现由非j...

Java调用本地接口常见错误

今天调用本地方法时遇到的问题: 1. java.lang.UnsatisfiedLinkError: no XXXX in java.library.path 2. Exception in ...

关于Classloader的总结!loadClass的分析和加载细节的分析

Java代码   package com.test.one;  import java.io.BufferedInputStream;  import java.io.ByteArrayOu...
  • pkuyjxu
  • pkuyjxu
  • 2013年02月27日 17:27
  • 4936

Java的native关键字

 今天研究Java基础类库,Object类的时候,发现了一个关键字:native咦?这是个什么东东?它认识我,我可不认识它!嘿嘿,没关系,baidu一下。 java native关键字 一. 什么是N...

Java 中通过jni接口调用native code

在上上篇中已经介绍了如何编译native code 生成 so动态库,这里再介绍下Java中如何通过JNI接口来调用动态库中的native code方法。 通过此篇文章,我们可以认识和了解如何完整...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Java 调用本地Native接口指引
举报原因:
原因补充:

(最多只允许输入30个字)