在Java代码中通过JNI调用C函数的步骤如下:

第一步:编写Java代码

第二步:编译Java代码(javac Java文件)

第三步:生成C代码头文件(javah java类名,自动生成)

第四步:编写C代码(实现C代码头文件里面的函数)

第五步:生成C共享库(使用工具编译生成C共享库,win下面为dll文件,Linux下面为so文件)

第六步:运行Java程序(java 类名)

一、编写Java代码

首先编写调用C语言的Java源代码HelloJNI.java

public class HelloJNI {
native void printHello(); native void printString(String str); static {
System.loadLibrary("hellojni");
} public static void main(String[] args) {
// TODO Auto-generated method stub
HelloJNI myJNI = new HelloJNI();
myJNI.printHello();
myJNI.printString("Hello world form printString function!");
}
}

说明:

1. 在Java类中,使用”native”关键字,声明本地方法,该方法与用C/C++编写的JNI本地函数相对应。”native”关键字告知Java编译器,在Java代码中带有该关键字的方法只是声明,具体由C/C++等其它语言编写实现。

2. 在Java类中声明了本地方法之后,接下来,调用System.loadLibrary()方法,加载具体实现本地方法的C运行库(在Java中加载本地运行库通常使用静态块(static block))。System.loadLibrary()方法加载由字符串参数指定的本地库,在不同操作系统平台下,加载的C运行库不同。在Window下面,调用System.loadLibrary(“hellojni”),则hellojni.dll会被加载;在Linux下面,则会加载libhellojni.so文件。

二、编译Java代码

使用javac编译java源代码

javac HelloJNI.java

三、生成C代码头文件

使用javah自动生成C代码头文件

javah HelloJNI

生成的头文件HelloJNI.h见下:

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class HelloJNI */ #ifndef _Included_HelloJNI
#define _Included_HelloJNI
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: HelloJNI
* Method: printHello
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_HelloJNI_printHello
(JNIEnv *, jobject); /*
* Class: HelloJNI
* Method: printString
* Signature: (Ljava/lang/String;)V
*/
JNIEXPORT void JNICALL Java_HelloJNI_printString
(JNIEnv *, jobject, jstring); #ifdef __cplusplus
}
#endif
#endif

四、编写C代码

实现C头文件中的方法,hellojni.c文件见下:

#include "HelloJNI.h"
#include <stdio.h>
JNIEXPORT void JNICALL Java_HelloJNI_printHello(JNIEnv *env, jobject obj)
{
printf("Hello world!\n");
return ;
} JNIEXPORT void JNICALL Java_HelloJNI_printString(JNIEnv *env, jobject obj, jstring string)
{
const char * str = (*env)->GetStringUTFChars(env,string,0);
printf("%s!\n",str);
return ;
}

说明:

1、GetStringUTFChars ()是JNI函数,用来将Java字符串转换成C语言字符串。JNI提供了多种JNI函数,用来处理C字符串与Java字符串的转换,具体参见http://blog.csdn.net/qinjuning/article/details/7595104

五、生成C共享库

在Linux下测试,书写makefile文件,编译刚才所写的C代码,生成.so文件;

makefile文件见下:

libhellojni.so:hellojni.o makefile
gcc -Wall -rdynamic -shared -o libhellojni.so hellojni.o
hellojni.o:hellojni.c HelloJNI.h
gcc -Wall -c hellojni.c -I./ -I/usr/lib/jdk/include -I/usr/lib/jdk/include/linux -fPIC
cl:
rm -rf *.o *.so

使用make命令编译

make

说明:

1、生成的so文件必须命令为libhellojni.so,与java代码中的System.loadLibrary("hellojni")对应;

2、在编译时,必须加上-fPIC,否则,编译时报以下错误:

/usr/bin/ld: hellojni.o: relocation R_X86_64_32 against `a local symbol' can not be used when making a shared object; recompile with -fPIC
hellojni.o: could not read symbols: Bad value
collect2: ld 返回 1
make: *** [hellojni.so] 错误 1

3、gcc和rm前面必须是一个tab空格,否则makefile格式不正确;

六、运行java程序

在运行java程序之前,要把生成的so文件加入LD_LIBRARY_PATH中,如下:

export LD_LIBRARY_PATH=./

否则,在运行java程序的时候报错,错误信息见下:

Exception in thread "main" java.lang.UnsatisfiedLinkError: no hellojni in java.library.path
at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1738)
at java.lang.Runtime.loadLibrary0(Runtime.java:823)
at java.lang.System.loadLibrary(System.java:1028)
at HelloJNI.<clinit>(HelloJNI.java:7)
Could not find the main class: HelloJNI. Program will exit.

运行java程序:

java HelloJNI

结果见下:

Hello world!
Hello world form printString function!!

在Java中调用C的更多相关文章

  1. Java中调用c/c++语言出现Exception in thread "main" java.lang.UnsatisfiedLinkError: Test.testPrint(Ljava/lang/String;)V...错误

    错误: Exception in thread "main" java.lang.UnsatisfiedLinkError: Test.testPrint(Ljava/lang/S ...

  2. java中调用dll文件的两种方法

    一中是用JNA方法,另外是用JNative方法,两种都是转载来的, JNA地址:http://blog.csdn.net/shendl/article/details/3589676   JNativ ...

  3. java中调用js脚本

    JDK1.6加入了对Script(JSR223)的支持.这是一个脚本框架,提供了让脚本语言来访问Java内部的方法.你可以在运行的时候找到脚本引擎,然后调用这个引擎去执行脚本.这个脚本API允许你为脚 ...

  4. autoit 处理文件上传弹出框,并在JAVA中调用

    Java  代码 //定义exe 文件存放的绝对路径 File file2 = new File("."); String command = file2.getCanonical ...

  5. 如何在Java中调用Python代码

    有时候,我们会碰到这样的问题:与A同学合作写代码,A同学只会写Python,而不会Java, 而你只会写Java并不擅长Python,并且发现难以用Java来重写对方的代码,这时,就不得不想方设法“调 ...

  6. 在Java中调用Python

    写在前面 在微服务架构大行其道的今天,对于将程序进行嵌套调用的做法其实并不可取,甚至显得有些愚蠢.当然,之所以要面对这个问题,或许是因为一些历史原因,或者仅仅是为了简单.恰好我在项目中就遇到了这个问题 ...

  7. JAVA中调用LevelDB用于Linux和Window环境下快速存储KV结构

    一.简介 JAVA中调用LevelDB用于Linux和Window环境下快速存储KV结构 二.依赖 <!-- https://mvnrepository.com/artifact/org.fus ...

  8. java中调用kettle转换文件

    java中调用kettle转换文件 通过命令行也能够调用,然后java中调用命令行代码也能够.这样没有和java代码逻辑无缝集成.本文说明kettle5.1中假设通过其它API和java代码无缝集成: ...

  9. 在Java中调用Python代码

    极少数时候,我们会碰到类似这样的问题:与A同学合作写代码, A同学只会写Python,不熟悉Java ,而你只会写Java不擅长Python,并且发现难以用Java来重写对方的代码,这时,就不得不想方 ...

  10. Java中调用MatLab返回值

    当在Java中使用MatLab函数时,由于语言语法的不同,Matlab返回多个数据时,想在Java中获取到并进行使用.查阅了网上资料,翻箱倒柜加上自己实战,得出方法如下: 如MatLab函数返回的是N ...

随机推荐

  1. 在ubuntu下配置apache运行python脚本

    2008-12-05    常用的简单命令 sudo apt-get remove --purge apache apache2 (彻底删除)   sudo /etc/init.d/apache2 r ...

  2. Base64 算法原理,以及编码、解码【加密、解密】 介绍

    Base64编码,是我们程序开发中经常使用到的编码方法.它是一种基于用64个可打印字符来表示二进制数据的表示方法.它通常用作存储.传输一些二进制数据编码方法!也是MIME(多用途互联网邮件扩展,主要用 ...

  3. Ubuntu 14.04 载入 JWS 或 访问 jsp异常的解决方法

    前段时间在Ubuntu 14.04中使用 Chrome登录 Webex准备面试的时候发现无法进入在线面试.搞笑的是前一天尝试进入 Webex的时候还一切正常,不过当时Webex的在线面试没有开始.等到 ...

  4. VS2012下安装NuGet

    关于NuGet的两篇文章:MSDN上的使用 NuGet 管理项目库,和博客园dudu的程序员,用NuGet管理好你的包包. VS2012下安装NuGet 在工具菜单下选择“扩展和更新”. 选择“联机” ...

  5. scanf中的[]

    今天被问到一个问题,如何用scanf将 hello-my-world中的三个单词, hello my world 分别放到三个char数组中去 于是用到了scanf中的[] [ ] 扫描字符集合,比如 ...

  6. NGUI 界面自适应

    关于 NGUI 的界面自动适应不同的手机分辨率,网上已经够多的了.如果你点进了这个网页,推荐一下这一篇吧: http://www.xuanyusong.com/archives/2536 下面是我自己 ...

  7. ruby -- 进阶学习(八)自定义方法route配置

     在route中进行修改,添加下面代码 namespace :mycontroller do get 'mymethod' , :on=> :member end end 注: :on => ...

  8. Gulp:新一代前端构建利器

    1.什么是Gulp gulp.js 是一种基于流的,代码优于配置的新一代构建工具. Gulp 和 Grunt 类似.但相比于 Grunt 的频繁的 IO 操作,Gulp 的流操作,能更快地完成构建. ...

  9. 【JVM学习笔记一】JVM内存分布

    Overview 学习JVM首先需要了解一下JVM管理的内存是如何分布的,在看了<深入理解Java虚拟机>和一些博文之后,我准备自己记录一下学习的过程. 下图是JVM中运行时数据区的大致示 ...

  10. AOP——代理技术

    一.如何理解代理技术 Proxy:不用你去做,别人代替你去处理.如Windows快捷方式,又如房屋中介 起到一个中介作用,通过代理对象,可以去掉客户不能看到的内容和服务或者添加客户需要的额外服务. 二 ...