- 浏览: 1524368 次
- 性别:
- 来自: 厦门
文章分类
- 全部博客 (516)
- Java (49)
- Java/Struts 2.0 (25)
- Java/Spring、Spring MVC (11)
- Java/Quartz (3)
- Java/Lucene (6)
- Java/Hibernate (19)
- Java/openJPA (7)
- Java/DWR (7)
- Java/Security、Spring Security/OAuth2 (6)
- Java/Threading (9)
- Java/XML (22)
- java/design pattern (4)
- Android (2)
- JavaScript (46)
- jquery (3)
- DB/MySQL (23)
- DB/Oracle (16)
- PHP (25)
- CSS (20)
- Linux (38)
- C/C++、DLL、Makefile、VC++ (31)
- 正则 (9)
- Eclipse (4)
- 安全、网络等概念 (25)
- 集群 (7)
- 网页 (5)
- 视频\音频 (1)
- HTML (6)
- 计算机数学/算法 (3)
- Virtualbox (1)
- LDAP (2)
- 数据挖掘 (6)
- 工具破解 (1)
- 其他 (13)
- Mail (1)
- 药材 (3)
- 游戏 (2)
- hadoop (13)
- 压力测试 (3)
- 设计模式 (3)
- java/Swing (2)
- 缓存/Memcache (0)
- 缓存/Redis (1)
- OSGI (2)
- OSGI/Gemini (0)
- 文档写作 (0)
- java/Servlet (3)
- MQ/RabbitMQ (2)
- MQ/RocketMQ (0)
- MQ/Kafka (1)
- maven (0)
- SYS/linux (1)
- cache/redis (1)
- DB/Mongodb (2)
- nginx (1)
- postman (1)
- 操作系统/ubuntu (1)
- golang (1)
- dubbo (1)
- 技术管理岗位 (0)
- mybatis-plus (0)
最新评论
-
pgx89112:
大神,请赐我一份这个示例的项目代码吧,万分感谢,1530259 ...
spring的rabbitmq配置 -
string2020:
不使用增强器 怎么弄?
OpenJPA的增强器 -
孟江波:
学习了,楼主,能否提供一份源代码啊,学习一下,十分感谢!!!4 ...
spring的rabbitmq配置 -
eachgray:
...
spring-data-redis配置事务 -
qljoeli:
学习了,楼主,能否提供一份源代码啊,学习一下,十分感谢!!!1 ...
spring的rabbitmq配置
转自:http://hi.baidu.com/injava/item/b9bf4de201e32210595dd878
JNI是Java Native Interface的英文缩写, 中文翻译为本地调用, 自从Java 1.1开始就成为了Java标准的一部分。
AD:
JNI是Java Native Interface的英文缩写, 中文翻译为本地调用, 自从Java 1.1开始就成为了Java标准的一部分。
C/C++是系统级的编程语言, 可以用来开发任何和系统相关的程序和类库, 但是Java本身编写底层的应用比较难实现, 使用JNI可以调用现有的本地库, 极大地灵活了Java的开发。
C/C++的效率是目前最好的语言, 可以使用C/C++来实现一些实时性非常高的部分. C/C++和Java本身都是非常流行的编程语言, 一些大型软件中经常使用语言之间的混合编程。
鉴于目前网络上JNI的文章不是特别多, 我将自己的一些总结写在这里. 如有错漏, 欢迎指正!
Java调用C/C++大概有这样几个步骤
- 编写带有native方法的Java类, 使用javac工具编译Java类
- 使用javah来生成与native方法对应的头文件
- 实现相应的头文件, 并编译为动态链接库(windows下是.dll, linux下是.so)
下 面就完整的介绍一个简单的Java调用C/C++的例子, 这个例子是来自http://www.ibm.com/developerworks/cn/education/java/j-jni /index.html, 不过其中有一些错误, 这个文章是非常不错的JNI学习资料, 但是非常古老.
编写Java类
我们来编写一个Sample1的java类
-
public class Sample1 {
public native int intMethod(int n);
public native boolean booleanMethod(boolean bool);
public native String stringMethod(String text);
public native int intArrayMethod(int[] intArray);
public static void main(String[] args) {
System.loadLibrary("Sample1");
Sample1 sample = new Sample1();
int square = sample.intMethod(5);
boolean bool = sample.booleanMethod(true);
String text = sample.stringMethod("Java");
int sum = sample.intArrayMethod(new int[]{1,2,3,4,5,8,13});
System.out.println("intMethod: " + square);
System.out.println("booleanMethod: " + bool);
System.out.println("stringMethod: " + text);
System.out.println("intArrayMethod: " + sum);
}
}
上面有4个native方法, 分别是4种类型的参数, int, boolean, String, int[].
其中有一句比较重要, 这句话加载了动态类库
- System.loadLibrary("Sample1");
在windows下加载的就是Sample1.dll, 在linux下加载的就是Sample1.so。
本文使用的windowws, 所以后面使用Sample1.dll来表示Sample1动态链接库。
注意:不可以在代码中写上后缀dll或so. 还要保证Sample1.dll在path路径中. 这个Sample1.dll是我们后面需要编译出来的东西。
4个native方法就是我们需要用C来实现的方法。
编译Sample1.java, 使用命令行(windows是cmd, linux下一般是bash)
>javac Sample1.java
可以看到Sample1.class文件
使用javah生成头文件
在命令行中运行
>javah Sample1
可以在目录下看到一个新文件Sample1.h
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class Sample1 */
#ifndef _Included_Sample1
#define _Included_Sample1
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: Sample1
* Method: intMethod
* Signature: (I)I
*/
JNIEXPORT jint JNICALL Java_Sample1_intMethod
(JNIEnv *, jobject, jint);
/*
* Class: Sample1
* Method: booleanMethod
* Signature: (Z)Z
*/
JNIEXPORT jboolean JNICALL Java_Sample1_booleanMethod
(JNIEnv *, jobject, jboolean);
/*
* Class: Sample1
* Method: stringMethod
* Signature: (Ljava/lang/String;)Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_Sample1_stringMethod
(JNIEnv *, jobject, jstring);
/*
* Class: Sample1
* Method: intArrayMethod
* Signature: ([I)I
*/
JNIEXPORT jint JNICALL Java_Sample1_intArrayMethod
(JNIEnv *, jobject, jintArray);
#ifdef __cplusplus
}
#endif
#endif
我们可以看到其中有四个函数声明, Java_完整类名_方法名, 完整类名包括了包名, 例如demo.Sample1是完整类名, 对应的这里就是demo_Sample1.
在注释中我们可以看到这样一个东西 Signature, 这个是方法的签名. 关于Signature, 下面通过一个表格来说明。
java 类型Signature备注 booleanZ byteB charC shortS intI longL floatF doubleD voidV objectL用/分割的 完整类名例如: Ljava/lang/String表示String类型Array[签名例如: [I表示int数组, [Ljava/lang/String表示String数组Method(参数签名)返回类型签名例如: ([I)I表示参数类型为int数组, 返回int类型的方法
上面头文件的第一个函数声明
- JNIEXPORT jint JNICALL Java_Sample1_intMethod (JNIEnv *, jobject, jint);
注释中的签名是 Signature: (I)I
在每个函数的参数列表中都有JNIEnv *和 jobject两个参数, 这两个参数稍候说明。
实现头文件中的函数
可以使用C语言来实现, 也可以使用C++来实现, 下面先说说C语言的实现。
#include "Sample1.h"
#include <string.h>
JNIEXPORT jint JNICALL Java_Sample1_intMethod
(JNIEnv *env, jobject obj, jint num)
{
return num * num;
}
JNIEXPORT jboolean JNICALL Java_Sample1_booleanMethod
(JNIEnv *env, jobject obj, jboolean boolean)
{
return !boolean;
}
JNIEXPORT jstring JNICALL Java_Sample1_stringMethod
(JNIEnv *env, jobject obj, jstring string)
{
const char* str = (*env)->GetStringUTFChars(env, string, 0);
char cap[128];
strcpy(cap, str);
(*env)->ReleaseStringUTFChars(env, string, 0);
return (*env)->NewStringUTF(env, strupr(cap));
}
JNIEXPORT jint JNICALL Java_Sample1_intArrayMethod
(JNIEnv *env, jobject obj, jintArray array)
{
int i, sum = 0;
jsize len = (*env)->GetArrayLength(env, array);
jint *body = (*env)->GetIntArrayElements(env, array, 0);
for (i = 0; i < len; ++i)
{
sum += body[i];
}
(*env)->ReleaseIntArrayElements(env, array, body, 0);
return sum;
}
(*env)->GetStringUTFChars()这个方法, 是用来在Java和C之间转换字符串的, 因为Java本身都使用了双字节的字符, 而C语言本身都是单字节的字符, 所以需要进行转换.
JNIEnv *是每个函数都有的参数, 它包含了很多有用的方法, 使用起来类似Java的反射, 也提供了这样一个编码转换的函数.
GetStringUTFChars()和NewStringUTF(), 第一个是从UTF8转换为C的编码格式, 第二个是根据C的字符串返回一个UTF8字符串.
ReleaseStringUTFChars()是用来释放对象的, 在Java中有虚拟机进行垃圾回收, 但是在C语言中, 这些对象必须手动回收. 否则可能造成内存泄漏.
函数的名字一眼看到就可以猜出功能, jni.h中的大部分函数名都是这样.
如果是C++的话, 这段代码该怎么写?
下面是C++的代码
#include "Sample1.h"
#include <string.h>
JNIEXPORT jint JNICALL Java_Sample1_intMethod
(JNIEnv *env, jobject obj, jint num)
{
return num * num;
}
JNIEXPORT jboolean JNICALL Java_Sample1_booleanMethod
(JNIEnv *env, jobject obj, jboolean boolean)
{
return !boolean;
}
JNIEXPORT jstring JNICALL Java_Sample1_stringMethod
(JNIEnv *env, jobject obj, jstring string)
{
const char* str = env->GetStringUTFChars(string, 0);
char cap[128];
strcpy(cap, str);
env->ReleaseStringUTFChars(string, 0);
return env->NewStringUTF(strupr(cap));
}
JNIEXPORT jint JNICALL Java_Sample1_intArrayMethod
(JNIEnv *env, jobject obj, jintArray array)
{
int i, sum = 0;
jsize len = env->GetArrayLength(array);
jint *body = env->GetIntArrayElements(array, 0);
for (i = 0; i < len; ++i)
{
sum += body[i];
}
env->ReleaseIntArrayElements(array, body, 0);
return sum;
}
上述两端代码非常相似, 只有一个不同点
C代码: (*env)->GetStringUTFChars(env, string, 0);
C++代码: env->GetStringUTFChars(string, 0);
C语言中使用的是结构体的函数指针, 而在C++中使用的还是struct, 我们知道struct在C++中和class的功能是几乎一样的, struct也可以用来定义类, 所以env在C++中是个类对象的指针.
编译和运行
这里使用的是微软编译器, 编译C语言版的dll
>cl -I%JAVA_HOME%\include -I%JAVA_HOME%\include\win32 -LD Sample1.c -FeSample1.dll
编译C++版本的dll
>cl -I%JAVA_HOME%\include -I%JAVA_HOME%\include\win32 -LD Sample1.cpp -FeSample1.dll
运行
>java Sample1
注意: 64位版本的JDK可能会在运行时报错:
java.lang.UnsatisfiedLinkError: ...Sample1.dll: Can't load IA 32-bit .dll on a AMD 64-bit platform
如果您有这样的错误, 请使用32位的JDK来重新运行.
运行结果如下:
intMethod: 25
booleanMethod: false
stringMethod: JAVA
intArrayMethod: 36
源代码下载: Sample1.zip
运行其中的build&run.bat文件即可, 如有错误请根据实际情况修改其中的一些参数.
DLL工程文件VC6.0和VS2010的: VC6.0&VS2010.zip
- Sample1.zip (2.9 KB)
- 下载次数: 0
- VC6.0_VS2010.zip (511.5 KB)
- 下载次数: 0
发表评论
-
HttpRequestClient
2018-11-21 17:45 591http请求工具 public class WebCon ... -
Spring boot 环境下配置CKEditor添加google map
2017-07-05 14:39 1253本文档基于已经搭建好基础ckeditor的环境上。如:ht ... -
post json
2015-12-30 12:35 535方法一: public static String doP ... -
maven打包成可执行的jar包(package a runnable jar)
2015-04-23 22:01 2215第一步:利用maven-jar-plugin生成当前工程的 ... -
自定义ObjectMapper
2015-03-02 16:57 7761d import java.io.IOExcept ... -
JsonObjectMapper
2015-02-05 10:41 1392import com.fasterxml.jackson. ... -
HttpServletRequestWrapper
2014-10-12 08:15 589请求提交后替换HTML字符 import javax.s ... -
配置javamelody
2014-09-12 14:03 1272参考后面地址修改整理。http://my.oschina.n ... -
getTrace()
2014-08-06 09:14 560/** * 将e.printStackTrace() ... -
获取java对象在内存的地址
2014-07-28 14:59 2862引用stackflow的文章:http://stackove ... -
JMeter入门:Java Request实例
2014-05-08 15:41 2346转自:http://softtest.chin ... -
解决在IE下下载时文件名乱码
2014-01-09 11:24 1053String agent = request.getHead ... -
第一节:编译自定义的Hadoop核心包,去除用户权限检查
2013-11-30 11:59 1062本文参考eclipse连接远程hadoop集群开发时0700 ... -
第二节:win 7下编译eclispe hadoop plugin
2013-11-29 19:12 832本文参照后面地址的Linux编译方式:http: ... -
使用log4j为Tomcat输出日志
2013-11-01 16:42 10339转自:http://hi.baidu.com/y ... -
xStream开发HTTP的XML内容
2013-07-03 09:58 10521、编写自定义XPPDriver代码: package ... -
HttpURLConnection or URLConnection post xml content to web server
2013-05-31 01:56 2056客户端示例1: package client; ... -
java nio学习笔记
2013-03-21 21:41 0直接缓冲区被用于与通道和固有I/O例程交互。它们 ... -
Jsch使用
2012-12-10 17:07 2541Jsch shell模式下的代码示例: 参考: ... -
Exe4j破解_Exe4j注册码
2012-12-06 17:35 33550exe4j是个很好的打包利器,官方下载地址:http://ww ...
相关推荐
Java通过JNI(Java Native Interface)调用C语言函数库是一种常见的技术实践,它允许Java程序直接与本地操作系统和硬件交互,提高性能或者利用已有的C/C++代码库。本资料"Java通过JNI调用C语言函数库的方法.zip"提供...
2. 本地方法:Java类可以声明本地方法,这些方法的实现是在C/C++中完成的,通过JNI接口调用。 3. 本地库加载:Java程序使用System.loadLibrary("library_name")来加载本地库(.dll或.so文件)。 二、JNI环境设置 1....
在Android开发中,NDK(Native Development Kit)是一个重要的工具集,它允许开发者使用C/C++语言编写部分或全部应用程序,以实现高性能计算或者利用已有的C/C++库。本项目是一个关于Android NDK入门的实例,展示了...
在本文中,我们将深入探讨如何在Visual Studio 2019环境下使用C++通过Java Native Interface (JNI)来调用Java代码。JNI是Java平台的一部分,它为Java应用程序提供了与本地代码交互的能力,使得开发者可以将Java应用...
JNI(Java Native Interface)是Java平台的标准组成部分,它允许Java代码和其他语言...通过学习和分析这个项目,开发者可以深入了解如何在Android应用中使用JNI调用C语言,从而实现混合编程,提升性能或实现特定功能。
在本示例中,Java程序通过JNI调用了C/C++实现的DLL(动态链接库)来执行特定的数学运算。以下是通过JNI调用DLL动态库的具体步骤和知识点: 1. **创建Java类**: 首先,我们需要在Java中创建一个类,声明native...
在Java应用程序中,JNI允许Java代码与用C、C++等本地语言编写的代码进行交互,实现了Java虚拟机(JVM)与本地代码的无缝连接。JNI在各种场景下都有广泛应用,例如性能优化、利用现有库、硬件访问等。 在这个“jni....
JNI提供了一套接口,这些接口定义了如何在Java虚拟机(JVM)中加载本地方法(即C/C++函数),以及如何与Java对象进行交互。在Java端,我们需要定义一个带有`native`关键字的方法,这告诉编译器这个方法将在本地代码...
在提供的资源"使用C++创建java虚拟机JVM,使用JNI调用java函数"中,可能详细介绍了以上步骤的实际应用,包括代码示例和可能遇到的问题及解决方案。通过学习和实践这个教程,开发者可以更好地理解和掌握C++与Java之间...
在Android开发中,JNI...总之,Android开发中的JNI调用涉及到Java/Kotlin与C/C++代码的混合编程,通过CMakeLists.txt进行编译配置,使两者能够高效地相互调用。熟悉这些操作对于提升应用性能、实现特定功能至关重要。
在Android开发中,JNI(Java Native Interface)是一个关键的组件,它允许Java代码与本地(C/C++)代码进行交互。JNI在许多场景下都扮演着重要的角色,比如提升性能、利用硬件加速、调用系统库或者第三方库,以及...
本项目涉及的"java调用C++动态链接库dll接口"是解决这种跨语言交互问题的一种方法,主要利用了Java Native Interface(JNA)这一技术。 JNA是Java平台的标准库,它允许Java代码直接调用本机库(如DLL或.so文件)的...
在本场景中,我们关注的是C++和Java的混合编程,这是一个常见的需求,尤其是在需要利用C++的高性能特性和Java的跨平台优势时。本文将深入探讨C++和Java混合编程的关键知识点,包括互操作性、接口设计、编译配置以及...
总结来说,Android中的本地代码调用上层Java实例涉及了JNI接口的使用,包括Java方法的声明、本地库的构建、以及在C/C++代码中调用Java方法的细节。这种混合编程方式让开发者能够充分利用Java和C/C++的优点,提高应用...
标题中的“JNI实现的DEMO Java调用VC编写的DLL,对应于Linux .SO”指的是一个使用Java Native Interface (JNI) 技术的示例,该示例展示了如何在Java程序中调用由Visual C++ (VC) 编译生成的动态链接库(DLL) 文件,...
在Java调用C++动态库的过程中,我们通常需要以下步骤: 1. **创建Java类并声明 native 方法**:在Java类中,我们需要声明将要由C++实现的函数,这些函数需要使用`native`关键字。例如: ```java public class JNI...
4. **加载本地库**:在Java程序中使用`System.loadLibrary`方法加载本地库。 #### 五、总结 通过使用JNI,开发者可以在Java程序中轻松地调用C++代码,从而结合两种语言的优点。本文介绍了如何在Java端声明native...
Java和C++之间的相互调用是跨语言编程中常见的需求,特别是在开发高性能、低级操作或者利用现有C/C++库的场景下。JNI(Java Native Interface)是Java平台标准的一部分,它提供了一种机制,使得Java代码能够调用C/...