原则上来说,“100%纯Java”的解决方法是最好的,但有些情况下必须使用本地方法。特别是在以下三种情况:

  • 需要访问Java平台无法访问的系统特性和设备;
  • 通过基准测试,发现Java代码比其他语言编写的等价代码慢得多;
  • 其他语言编写的代码已经经过大量测试和调试,并且知道如何将其导出到所有的目标平台上。

  Java平台有一个用于和本地C、C++代码进行互操作的API,称为Java本地接口(JNI)。下面将举例讨论Linux平台下的JNI编程。

1. 创建java类文件

  创建一个nativeTest包,在包下新建HelloNative.java文件。

 package nativeTest;

 /**
* Created by jiax on 2016/12/30.
*/
public class HelloNative {
// 静态初始化代码块,保证虚拟机在第一次使用该类时就会装载库
static {
System.loadLibrary( "HelloNative" );
} // native 关键字表示本地方法,提醒编译器该方法将在外部定义
public static native void greeting(); // 测试greeting()函数
public static void main(String[] args) {
greeting();
}
}

2. 生成.h头文件

  使用以下命令生成一个C的头文件,nativeTest_HelloNative.h

 javac HelloNative.java
cd ..
javah nativeTest.HelloNative

  生成的nativeTest_HelloNative.h如下:

 /* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class nativeTest_HelloNative */ #ifndef _Included_nativeTest_HelloNative
#define _Included_nativeTest_HelloNative
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: nativeTest_HelloNative
* Method: greeting
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_nativeTest_HelloNative_greeting
(JNIEnv *, jclass); #ifdef __cplusplus
}
#endif
#endif

nativeTest_HelloNative.h

  这个文件是在nativeTest文件夹外生成的,需要拖到nativeTest文件夹里面。  

3. 创建.c文件

  新建一个HelloNative.c文件,写出greeting()函数的实现代码。

 #include <stdio.h>
#include "nativeTest_HelloNative.h" JNIEXPORT void JNICALL Java_nativeTest_HelloNative_greeting(JNIEnv *env, jobject c1) {
printf("Hello Native!!\n");
}

4. 编译一个动态链接库

  使用Linux下的gcc编译器,命令如下:

gcc -fPIC -I $JAVA_HOME/include -I $JAVA_HOME/include/linux -shared -o libHelloNative.so HelloNative.c

  生成libMyNative.so文件,此时整个nativeTest目录文件结构如下:

5. 运行测试

  输入如下命令运行HelloNative.class文件。

java nativeTest.HelloNative 

  如果出现如下错误:

  则需要把libHelloNative.so所在文件夹加入java.library.path,使用命令:

export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:..../nativeTest

  最终结果如下。

6 总结

  总的来说,将一个本地方法链接到Java程序中需要经过以下5个步骤:

  1. 在Java类中声明一个本地方法;
  2. 运行javah以获得包含该方法的C声明的头文件;
  3. 用C实现该本地方法;
  4. 将代码置于共享类库中;
  5. 在Java程序中加载该类库。

附录——本文中用到的工具版本

JDK——1.8.0_111

gcc——4.8.5

Linux上从Java程序中调用C函数的更多相关文章

  1. 在网页程序或Java程序中调用接口实现短信猫收发短信的解决方案

    方案特点: 在网页程序或Java程序中调用接口实现短信猫收发短信的解决方案,简化软件开发流程,减少各应用系统相同模块的重复开发工作,提高系统稳定性和可靠性. 基于HTTP协议的开发接口 使用特点在网页 ...

  2. Java程序中调用Python脚本的方法

    在程序开发中,有时候需要Java程序中调用相关Python脚本,以下内容记录了先关步骤和可能出现问题的解决办法. 1.在Eclipse中新建Maven工程: 2.pom.xml文件中添加如下依赖包之后 ...

  3. 如何在java程序中调用linux命令或者shell脚本

    转自:http://blog.sina.com.cn/s/blog_6433391301019bpn.html 在java程序中如何调用linux的命令?如何调用shell脚本呢? 这里不得不提到ja ...

  4. java程序中调用Linux命令Windows命令

    目前总结的方法: 调用Linux简单的命令行,设置文件夹权限755 String scriptDir = "/home/wenf"; String cmd = "chmo ...

  5. Linux上分析java程序的问题

    通过日志看不出来的问题,可以通过看java的堆栈信息(dump文件)来看出一些端倪. 1. 找java的进程id.jdk/bin的目录 ps -ef | grep java 2. cd 到bin的目录 ...

  6. Android驱动入门-在Android系统上运行JAVA程序

    在linux上运行java程序,直接用javac编译,再用java运行就行了.但是在Android上,由于虚拟机和pc端的不同,所以操作方法也是不一样的. 如果想在Android上运行Hello wo ...

  7. linux(ubuntu) 搭建java程序运行环境

    一:简介 ubuntu 系统的和linux差不多,我们需要在系统上搭建java程序运行环境,需要安装jdk,mysql这两个软件,tomcat是绿色版,直接通过taz -zxvf tomcat 就可以 ...

  8. 如何在 Linux 上安装应用程序

    如何在 Linux 上安装应用程序 编译自:https://opensource.com/article/18/1/how-install-apps-linux作者: Seth Kenlon原创:LC ...

  9. 如何使用加多宝(jdb)在linux下调试Java程序

    毕业时写了一段时间的C,那时候调试使用gdb,后来转了java,当时就想java程序怎么调试,找了一下,果然,那就是jdk自带的jdb windows里是这样的 Linux下是这样的 一般我在linu ...

随机推荐

  1. canvas绘制二次贝塞尔曲线----演示二次贝塞尔四个参数的作用

    canvas中绘制二次贝塞尔曲线的方法为ctx.quadraticCurveTo(x1,y1,x2,y2); 四个参数分别为两个控制点的坐标.开始点即当前canvas中目前的点,如果想从指定的点开始, ...

  2. js中列表控件排序箭头,在wke中不支持的解决办法

    列表中箭头,实际使用的在线css样式,wke不支持排序箭头(实际是字体)的在线css样式,可以客户端安装对应的字体,之后显示就正常了.

  3. InnoDB杂记

    一.InnoDB写数据流程(猜想) myisam是将索引放入内存缓存(Key Cache,大小有key_buffer_size设置) innodb时间索引和数据文件都放入内存缓存池(Buffer Po ...

  4. Servlet中的常用类以及常用方法

    A:ServletConfig:用于读取Servlet在web.xml中配置的一些信息. getServletName(); getInitParameter();只能是Servlet自身下的参数设置 ...

  5. iOS版本更新的App提交审核发布流程

    http://www.2cto.com/kf/201502/378698.html 版本更新的App和新App的发布提交流程略有不同,新的App需要在开发者账号里准备发布证书,添加App的id,关联描 ...

  6. ORM系列之二:EF(4) 约定、注释、Fluent API

    目录 1.前言 2.约定 2.1 主键约定 2.2 关系约定 2.3 复杂类型约定 3.数据注释 3.1 主键 3.2 必需 3.3 MaxLength和MinLength 3.4 NotMapped ...

  7. 基于ssh框架开发的购物系统的质量属性

    根据前面的博客,我们已经大致了解了ssh架构开发整体概念:Struts是一个实现了MVC模式的经典的框架:Hibernate是轻量级Java EE应用的持久层解决方案,以面向对象的方式提供了持久化类到 ...

  8. ubuntu 更改时区

    更改/etc/timezone Asia/Chongqing sudo dpkg-reconfigure tzdata

  9. Qt容器类——1. QList类、QLinkedList类和QVector类

    在开发一个较高性能需求的应用程序时,程序员会比较关注这些容器类的运行效率,表2.1列出了QList.QLinkedList和QVector容器的时间复杂度比较. 1.QList类 QList<T ...

  10. Java提高篇——设计模式

    设计模式简介 设计模式(Design pattern)代表了最佳的实践,通常被有经验的面向对象的软件开发人员所采用.设计模式是软件开发人员在软件开发过程中面临的一般问题的解决方案.这些解决方案是众多软 ...