本地方法(JNI)——从java 程序中调用C函数

【0】README

1) 本文部分文字描述 转自 core java volume 2 , 旨在理解 本地方法——从java 程序中调用C函数 的基础知识 ;
2) for source code, please visit https://github.com/pacosonTang/core-java-volume/tree/master/coreJavaAdvanced/chapter12/javaCassFuncOfC

【1】本地方法相关

1)本地代码定义: 原则上说, 100% 纯 java 的解决方案是非常好的, 但有时你也会想要编写或使用其他语言的代码, 这种代码就称为本地代码;
2)我们建议只有在必需的时候才使用本地代码, 特别是在以下三种情况的时候(cases):

  • c1)你的应用需要访问的系统特性和设备通过java 平台无法实现;
  • c2)你已经有了大量的测试过 和 调试过的 用另一种语言编写的代码, 并且知道如何将其导出到所有的目标平台上;
  • c3)通过基准测试, 你发现所编写的 java 代码比用另一种语言编写的等价代码要慢很多;

3)java 本地接口(JNI): java 平台有一个用于和本地C 代码进行交互操作的 API, 称为java 本地接口(JNI);


【2】从java 程序中调用C函数

1) 关键字native: java 使用 native 表示本地方法;

class HelloNative
{  public static native void greeting();
}

2)本地方法: 既可以是静态的,也可以是非静态的;
3)为了实现本地代码: 需要编写一个C 函数,你必须完全按照 java 虚拟机预期的那样来命名这个函数。 其规则是(rules):

  • r1)使用完整的java 方法名:

    如 HelloNative.greeting; 如果属于某个包还要添加包名, 如 com.corejava.HelloNative.greeting;

  • r2)用下划线替换掉所有的句号, 并加上 Java_前缀, 如:

    Java_com_corejava_HelloNative_greeting;

  • r3)如果类名含有非 ASCII 字母或数字:

    如:’_’, ‘$’ 或是 大于 ‘\u007F’ 的 unicode 字符,用_0xxxx 来替代它们, xxxx 是该字符的unicode 值的 4个十六进制数序列;

Attention)

  • A1)如果你重载本地方法, 也就是说, 你用相同的名字提供多个本地方法, 那么你必须在名称后面附加两个下划线, 后面再加上已编码的参数类型;
  • A2) 看个荔枝: 如果你有一个本地方法 greeting 和 本地方法 greeting(int repeat), 那么第一个称为 Java_HelloNative_greeting__, 第二个称为 Java_HelloNative_greeting_I;
  • A3)javah程序:没有人完成这些手工操作, javah 自动生成函数名;

4)java程序调用C函数的实现steps:

  • (javah导出类的头文件可能抛出异常——java.lang.IllegalArgumentException: Not a valid class name, for solution, please visit http://blog.csdn.net/pacosonswjtu/article/details/50615988)

  • step1)用 javah 生成函数名:

  • 这里写图片描述

  • 对以上代码的分析(Analysis):

    • A1) 这个头文件包含了函数 Java_HelloNative_greeting 的声明;
    • A2) 字符串 JNIEXPORT 和 JNICALL 是在头文件 jni.h 中定义的, 他们为那些来自动态装载库的导出函数标明了 依赖于编译器的说明符;
  • step2)现在,需要将 函数原型从头文件中 复制到源文件中, 并且给出函数的实现代码(新建 HelloNative.c);
    这里写图片描述

  • step3) 将本地C 代码编译到一个动态装载库中, 具体方法依赖于编译器;

    • step3.1) Linux 下的 GNU C 编译器:

      使用如下命令:(1) gcc -fPIC -I jdk/include -I jdk/include/linux -shared -o libHelloNative.so HelloNative.c 或
      (2.1) gcc -c -I /usr/java/jdk1.7/include/ -I /usr/java/jdk1.7/include/linux/ HelloNative.c
      (2.2) gcc -shared -fPIC -o HelloNative.so HelloNative.o

    • step3.2)使用windows 下的微软编译器:

      命令是: cl -I jdk/include -I >jdk/include/win32 -LD HelloNative.c -FeHelloNative.dll

    • step3.3)通过cygwin 环境下 将本地C 代码编译到动态装载库中:

      gcc -mno-cygwin -D __int64=”long long” -I jdk/include/win32 -shared -Wl, –add-stdcall-alias -o HelloNative.dll HelloNative.c

  • step4) 最后,我们要在程序中添加 一个对 System.loadLibrary 方法的调用。为了确保虚拟机第一次使用该类之前就会装载这个库, 需要使用 静态初始化代码块。 如下所示:
    这里写图片描述

Attention)如果运行在 Linux 下, 必须把当前目录添加到库路径中。

  • A1)实现的方式可以是通过设置 LD_LIBRARY_PATH 环境变量:

    export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH

  • A2)或者是设置 java.library.path 系统属性:

    java -Djava.library.path=. HelloNativeTest

Conclusion) 总之,遵循下面的steps就可以将一个本地方法链接到 java 程序中:

  • step1)在 java类中声明一个本地方法;

    package com.corejava.chapter12;public class HelloNative
    {  public static native void greeting();
    }
    
  • step2) 运行javah 以获得包含该方法的 C 声明的头文件;

  • step2.1)编译文件: javac com/corejava/chapter12/HelloNative.java

  • step2.2)javah生成该类的头文件: javah com.corejava.chapter12.HelloNative
    这里写图片描述

step3) 用 C 实现该本地方法:

  • step3.1)将 相应的方法原型(返回类型,方法名,参数列表) copy 到 .c 文件中,并实现该方法):
#include "com_corejava_chapter12_HelloNative.h"
#include <stdio.h>
JNIEXPORT void JNICALL Java_com_corejava_chapter12_HelloNative_greeting(JNIEnv * env, jclass) 
{printf("hello world ! this greeting is from native method by C");
}
  • 这里写图片描述

  • step3.2)在linux环境下, 将本地C 代码编译到动态装载库中

    gcc -c -I /usr/java/jdk1.7/include/ -I /usr/java/jdk1.7/include/linux/ HelloNative.c
    gcc -shared -fPIC -o libHelloNative.so HelloNative.o

  • step4)将代码置于 共享类库中;
    这里写图片描述

  • 这里写图片描述

  • step5) 在 java 程序中 加载该类库(java类中的main调用C函数)
    这里写图片描述

    • Warning) 这里运行可能出错,throw exception : java.lang.UnsatisfiedLinkError: no yourClassName in java.library.path , 这也就是 为什么本文先打印出了 java.library.path, 然后将 libHelloNative.so 添加到该共享库中的原因;当然了, for detailed spec , you can also refer to http://blog.csdn.net/pacosonswjtu/article/details/50618033

Conclusion) 最后的工作目录文件列表如下:
这里写图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/331483.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Hadoop入门(一)概念与单机安装

一、hadoop的概念 &#xff08;1&#xff09;什么是大数据 大数据是不能用传统的计算技术处理的大型数据集的集合。它不是一个单一的技术或工具&#xff0c;而是涉及的业务和技术的许多领域。 &#xff08;2&#xff09;hadoop的定义 Hadoop是一个由Apache基金会所开发的分布式…

螺旋测微器 flash_使用测微计收集应用程序指标

螺旋测微器 flash什么是Micrometer&#xff1f; Micrometer是一个简单的外观&#xff0c;用于以供应商中立的方式收集Java应用程序中的指标。 您可以考虑使用SLF4J作为指标。 Micrometer内置了对许多不同指标后端的内置支持&#xff0c;包括Atlas&#xff0c;Datadog&#xff0…

java JNI调用C语言动态链接库(java.lang.UnsatisfiedLinkError: no yourClassName in java.library.path 异常的解决方法)

转自&#xff1a; http://watershitter.iteye.com/blog/477615今天花了至少3个小时跑这个java调c的动态链接库的Hello&#xff0c;native world的程序。 把所有犯的错误和要点总结一下! 1 java 中 c语言函数的声明 public native static void greeting(); //就像是接口声明一样…

Hadoop入门(二)集群安装

一、集群安装条件前置 在虚拟机上先准备一个机子 按用前面【安装单机hadoop】 已完成安装jdk,hadoop和ssh、网络等配置环境等。 虚拟机和操作系统 环境&#xff1a;ubuntu14 hadoop2.6jdk1.7ssh 虚拟机&#xff1a;&#xff08;vmware10&#xff09; 二、集群安装环境设置…

poj doubles_余数运算符在Java中用于Doubles

poj doubles我在OSU任教已近两年了&#xff0c;这总是令我惊讶&#xff0c;我从学生那里学到了多少。 例如&#xff0c;过去&#xff0c; 我让学生写一些我不理解的奇怪代码 。 在这一点上&#xff0c;即使经过300多个博客文章&#xff0c; 几个YouTube视频 &#xff0c;甚至还…

面向对象与面向过程

一、面向过程编程 面向过程编程是一种以过程为中心的编程思想,分析出解决问题的步骤&#xff0c;然后用函数把这些步骤一步一步实现。面向过程编程&#xff0c;数据和对数据的操作是分离的。二、面向对象编程 面向对象编程是将事物对象化&#xff0c;通过对象通信来解决问题。面…

本地方法(JNI)——数值参数与返回值

【0】README 1&#xff09; 本文部分文字描述 转自 core java volume 2 &#xff0c; 旨在理解 本地方法&#xff08;JNI&#xff09;——数值参数与返回值 的基础知识 &#xff1b; 2&#xff09; for source code, please visit https://github.com/pacosonTang/core-java…

class employe_Java 8 –集合sort()方法–按Employe对象(Id,名称,年龄)列出自定义排序示例

class employe有关在Java中对自定义对象进行排序的完整指南。 Collections.sort&#xff08;&#xff09;方法基于Comparable或Comparator实现进行排序。 用于对Employee对象进行排序的示例自定义排序 1.简介 在本教程中&#xff0c;您将学习如何在java中对Custom对象进行排序…

Spring入门(一)之简介

一、Spring定义 Spring是一个开源框架&#xff0c;Spring是于2003 年兴起的一个轻量级的Java 开发框架&#xff0c;由Rod Johnson创建。 简单来说&#xff0c;Spring是一个分层的JavaSE/javaEE full-stack(全栈的) 轻量级开源框架。 二、Spring框架特征 &#xff08;1&#xff…

本地方法(JNI)——访问域+字符串参数

【0】README 1&#xff09; 本文部分文字描述 转自 core java volume 2 &#xff0c; 旨在理解 本地方法&#xff08;JNI&#xff09;——访问域字符串参数 的基础知识 &#xff1b; 2&#xff09; for source code, please visit https://github.com/pacosonTang/core-java…

aws上负载均衡器标组端口_AWS CloudFormation:目标组没有关联的负载均衡器

aws上负载均衡器标组端口昨天&#xff0c;我使用AWS CloudFormation模板最终创建了ECS服务&#xff08;Fargate类型&#xff09;&#xff0c;还创建了包括应用程序负载均衡器&#xff0c;目标组和IAM角色的资源。 创建堆栈时&#xff0c;出现以下错误&#xff1a; 具有target…

Spring入门(二)之下载与安装

一、Spring下载 参考其他博客&#xff1a;http://www.cnblogs.com/yjmyzz/p/3847364.html或http://blog.csdn.net/xinzhujin/article/details/54319043 Spring下载地址为&#xff1a;http://repo.spring.io/release/org/springframework/spring/ 二、压缩包下的SpringFramewo…

HttpClient 4 API –获取状态代码-getStatusLine()。getStatusCode()示例

在HttpClient API中获取状态代码的快速指南。 getStatusLine&#xff08;&#xff09;。getStatusCode&#xff08;&#xff09;示例和相关的错误。 1.简介 在这个非常快速的教程中&#xff0c;我将展示如何使用HttpClient 4获取和验证HTTP响应的StatusCode。 2. Maven依赖 要…

Spring入门(三)之IoC

一、IoC定义IoC&#xff0c;即控制反转。开发者在使用类的实例之前&#xff0c;需要先创建对象的实例。但是IoC将创建实例的任务交给IoC容器&#xff0c;这样开发应用代码时只需要直接使用类的实例&#xff0c;这就是IoC。在讨论控制反转这个概念的过程中&#xff0c;Martin Fo…

云服务器的优点和缺点_为什么要使用云计算? 的优点和缺点

云服务器的优点和缺点在过去的几年中&#xff0c;云计算一直是IT界的热门话题。 像许多事物一样&#xff0c;当它第一次出现时&#xff0c;很多人都将其视为下一件大事&#xff0c;但是云计算确实达到了期望&#xff0c;并真正改变了当今信息技术业务部门的运作方式。 云计算由…

本地方法(JNI)——编码签名

【0】README 1&#xff09; 本文部分文字描述 转自 core java volume 2 &#xff0c; 旨在理解 本地方法&#xff08;JNI&#xff09;——编码签名 的基础知识 &#xff1b; 【1】编码签名相关 1&#xff09; 混编规则&#xff1a;为了访问实例域和调用用 java 定义的方法&a…

Shell入门(一)之简介

一、Shell 定义 &#xff08;1&#xff09;Shell Shell是一个用 C 语言编写的程序&#xff0c;它是用户使用 Linux 的桥梁。Shell 既是一种命令语言&#xff0c;又是一种程序设计语言。 &#xff08;2&#xff09;Shell 脚本&#xff08;shell script&#xff09; Shell 脚本…

aws dynamodb_使用适用于Java 2的AWS开发工具包的AWS DynamoDB版本字段

aws dynamodb将任何实体上的版本属性保存到 AWS DynamoDB数据库&#xff0c;它只是表示已修改实体次数的数字表示。 首次创建实体时&#xff0c;可以将其设置为1&#xff0c;然后在每次更新时递增。 好处是立竿见影的-指示实体已被修改的次数&#xff0c;可用于审核实体。 此…

本地方法(JNI)——调用 java 方法

【0】README 1&#xff09; 本文部分文字描述 转自 core java volume 2 &#xff0c; 旨在理解 本地方法&#xff08;JNI&#xff09;——调用 java 方法 的基础知识 &#xff1b; 2&#xff09; C语言调用java 方法&#xff0c;包括&#xff1a; 静态C 方法 和 非静态C 方法…

Shell入门(二)之变量

一、shell变量类型 shell变量一般只有两种类型&#xff1a;数值型与字符串型。 运行shell时&#xff0c;会同时存在三种变量&#xff1a; 1) 局部变量 局部变量在脚本或命令中定义&#xff0c;仅在当前shell实例中有效&#xff0c;其他shell启动的程序不能访问局部变量。 …