JNI使用技巧点滴

JNI使用的一些细节和用法 本文章分二部分: 一.首先看如何绑定JNI和JAVA的方法 我们要特别留意下JNI_OnLoad,百度下之后: 当Android的VM(Virtual Machine)执行到C组件(即so档)里的System.loadLibrary()函数时, 首先会去执行C组件里的JNI_OnLoad()函数。 它的用途有二: . 告诉VM此C组件使用那一个JNI版本。 如果你的.so档没有提供JNI_On... 阅读详情

摘要

 

本文为在 32 位 Windows 平台上实现 Java 本地方法提供了实用的示例、步骤和准则。本文中的示例使用 Sun Microsystems 公司创建的 Java Development Kit (JDK) 版本 1.4.1 。用 C 语言编写的本地代码是用 Microsoft Visual C++ 编译器编译生成。

 

简介

 

近日,由于项目需要,要在WEB页面实现图像转换功能,而VC在图像转换方面有着得天独厚的优势。我们首先用VC封装出图像转换的DLL,然后用JAVA的本地化方法JNI调用用于图像转换的DLL,最后用JavaBean调用JNI生成的DLL。

 

通过近几天在网上找资料和自己的摸索,收获很多,现总结如下,让以后做这方面的人少走弯路。

 

一.JAVA部分

 

1.无包的情况:

实例一:

public class MyNative

{

     static

     {

           System.loadLibrary( "MyNative" );

     }

     public native static void HelloWord();

     public native static String cToJava();

}

 

说明:

1)    在JAVA程序中,首先需要在类中声明所调用的库名称System.loadLibrary( String libname );,在库的搜寻路径中定位这个库。定位库的具体操作依赖于操作系统。在windows下,首先从当前目录查找,然后再搜寻”PATH”环境变量列出的目录。如果找不到该库,则会抛出UnsatisfiedLinkError。

2)      这里加载的是JNI生成的DLL,而不是其他生成的DLL的名称。?在这里,库的扩展名字可以不用写出来,究竟是DLL还是SO,由系统自己判断。

3)       还需要对将要调用的方法做本地声明,关键字为native。并且只需要声明,而不需要具体实现。?实现放在C中实现,稍后将做说明。

4)       如果加了static,表明是静态方法。如果不加,表明是一般的方法。加与不加,生成的头文件中有一个参数不同。稍后将做说明。

 

现在开始编译它:

用javac MyNative.h编译它,生成对应的class文件。

用javah MyNative ,就会生成对应的MyNative.h头文件。剩下的是就开始交给VC来完成了(我们用VC来实现对应的C实现部分)。

 

2. 有包的情况:

实例二:

package? com..myNative;

public class MyNative

{

       static

       {

               System.loadLibrary( "MyNative" );

       }

       public native static void HelloWord();

       public native static String cToJava();

}

其他与上面相同,就是在用javac和javah时有所不同。对于有包的情况一定要注意这一点,开始时我的程序始终运行都不成功,问题就出在这里。

javac ./com/myNative/MyNative.java

javah com.myNative.MyNative

 

上面一句就不用解释了。对下面的一句解释一下:本类的前面均是包名。这样生成的头文件就是:com.myNative.MyNative.h。 开始时,在这种情况下我用javah MyNative生成的头文件始终是MyNative.h。在网上查资料时,看见别人的头文件名砸那长,我的那短。但不知道为什么,现在大家和我一样知道为什么了吧。:)。有时还需要带上路径。具体查看javah的语法。

 

二.C实现部分

刚才用javah MyNative生成的MyNative.h头文件内容如下:

 

/* DO NOT EDIT THIS FILE - it is machine generated */

#include

/* Header for class MyNative */

#ifndef _Included_MyNative

#define _Included_MyNative

#ifdef __cplusplus

extern "C" {

#endif

/*

          * Class: MyNative

          * Method:HelloWord

          * Signature: ()V

 */

JNIEXPORT void JNICALL Java_MyNative_HelloWord (JNIEnv *, jclass);

/*

          * Class:  MyNative

          * Method: cToJava

 * Signature: ()Ljava/lang/String;

 */

JNIEXPORT jstring JNICALL Java_MyNative_cToJava? (JNIEnv *, jclass);

#ifdef __cplusplus

}

#endif

#endif

 

接下来,就是如何实现它了。其实,用JNI作出的东西也是DLL,被JAVA所调用。

在具体实现的时候,我们只关心两个函数原型:

JNIEXPORT void JNICALL Java_MyNative_HelloWord(JNIEnv *, jclass);和JNIEXPORT jstring JNICALL Java_MyNative_cToJava(JNIEnv *, jclass);

 

现在让我们开始激动人心的第一步吧 : ) 。在project里面选择win32 Dynamic-link Library,然后点击下一步,其余的取默认。如果不取默认的,将会有dllmain()函数。取空DLL工程的话,将无这个函数。我在这里取的是空。

然后选择new->File->C++ Source? File,生成一个空*.cpp文件。我们把他取名为MyNative。把JNIEXPORT void JNICALL Java_MyNative_HelloWord(JNIEnv *, jclass);和JNIEXPORT jstring JNICALL Java_MyNative_cToJava(JNIEnv *, jclass);拷贝到CPP文件中去。然后把头文件包含进来。

 

生成的MyNative.cpp内容如下:

#include

#include "MyNative.h"

 

        JNIEXPORT void JNICALL Java_MyNative_HelloWord? (JNIEnv *env, jclass jobject)

{

                   printf("hello word!/n");

}

JNIEXPORT jstring JNICALL Java_MyNative_cToJavaJNIEnv *env, jclass obj)

{

                   jstring jstr;

                  char str[]="Hello,word!/n";

                   jstr=env->NewStringUTF(str);

                  return jstr;

 }

 

在编译前一定要注意下列情况。

注意:一定要把SDK中的include文件夹中(和它下面的win32文件夹下的头文件)的几个头文件拷贝到VC的include文件夹中。或者在VC的tools/options/directories中设置,把头文件给包含进来。

 

对程序的一点解释:

1)       前文不是说过,加了static和不加只是一个参数的区别吗。就是jclass的不同,不加static这里就是jobject。也就是JNIEXPORT void JNICALL Java_MyNative_HelloWord(JNIEnv *env, jobject obj)。

2)      这里JNIEXPORT和JNICALL都是JNI的关键字,表示此函数是要被JNI调用的。而jstring是以JNI为中介使JAVA的String类型与本地的string沟通的一种类型,我们可以视而不见,就当做String使用(具体对应见表一)。函数的名称是JAVA_再加上java程序的package路径再加函数名组成的(参见有包的情况)。参数中,我们也只需要关心在JAVA程序中存在的参数,至于JNIEnv*和jclass我们一般没有必要去碰它。

3)       NewStringUTF()是JNI函数,从一个包含UTF格式编码字符的char类型数组中创建一个新的jstring对象。

4)       以上程序片断jstr=env->NewStringUTF(str);是C++中的写法,不必使用env指针。因为JNIEnv函数的C++版本包含有直接插入成员函数,他们负责查找函数指针。而对于C的写法,应改为:jstr=(*env)->NewStringUTF(env,str);因为所有JNI函数的调用都使用env指针,它是任意一个本地方法的第一个参数。env指针是指向一个函数指针表的指针。因此在每个JNI函数访问前加前缀(*env)->,以确保间接引用函数指针。

 

在C和Java编程语言之间传送值时,需要理解这些值类型在这两种语言间的对应关系。这些都在头文件jni.h中,用typedef语句声明了这些类在目标平台上的代价类。头文件也定义了常量如:JNI_FALSE=0 和JNI_TRUE=1;表一说明了Java类型和C类型之间的对应关系。

 

表一  Java类型和C类型

 

Java编程语言

C编程语言

字节

boolean

jboolean

1

byte

jbyte

1

char

jchar

2

short

jshort

2

int

jint

4

long

jlong

8

float

jfloat

4

double

jdouble

8

 

 

现在开始对所写的程序进行编译。选择build->rebuild all对所写的程序进行编译。点击build->build MyNative.DLL生成DLL文件。

也可以用命令行cl来编译。具体参看其他书籍。

 

再次强调(曾经为这个东西大伤脑筋):DLL放置地方

1)      当前目录。

2)      放在path所指的路径中

3)      自己在path环境变量中设置一个路径,要注意所指引的路径应该到.dll文件的上一级,如果指到.dll,则会报错。

 

下面就开始测试我们的所写的DLL吧(假设DLL已放置正确)。

public class mytest

{

          public static void main(String[] args)

         {

                    MyNative a=new MyNative();

                    a.HelloWord();

                    System.out.println(a.cToJava());

          }

}

 

注意也要把MyNative.class放在与mytest.java同一个路径下。现在开始编译运行mytest,是不是在DOS窗口上输出:

Hello word!

Hello,world!

以上是我们通过JNI方法调用的一个简单C程序。但在实际情况中要比这复杂的多。特别是在通过JNI调用其他DLL时,还有很多的地方需要注意。

 

现在开始来讨论包含包的情况,步骤与上面的相同,只是有一点点不同。我们来看其中的一个函数。

JNIEXPORT void JNICALL Java_com_MyNative_MyNative_HelloWord (JNIEnv *env, jclass jobject)

{

                         printf("hello word!/n");

         }

我们来观察函数名称。函数的名称是JAVA_再加上java程序的package路径再加函数名组成的。现在这句话应该理解了吧。

我们也写一个程序来测试包含包的情况。程序略。

javac ./com/MyNative/mytest.java

java mytest

是不是在DOS窗口上也显示同样的内容:)。

 

 

这次,就到这里吧,下一讲将讲述JNI调用其他DLL时应该注意的地方,同时会给出一个具体的例子。也将会给出一个UNICODE编码和ASCII编码之间互相转换的通用函数。如果有什么疑问可以与我交流:normalnotebook@126.com

Qwen3-VL、Qwen3-Next与Qwen3.5多模态架构深度解剖 多模态大模型的核心不在参数规模,而在于视觉与文本如何协同建模。本文从基础概念切入,解析视觉语言模型中视觉编码器、跨模态注意力、特征对齐与token压缩等关键原理;阐述ViT、CLIP-ViT及动态压缩模块(HDTC)在语义表征、空间感知与计算效率上的技术权衡;强调结构设计如何决定模型在医学影像、工业质检、遥感分析等高要求场景中的真实能力边界;最终聚焦通义千问最新三套VL架构——Qwen3-VL、Qwen3-Next与Qwen3.5——揭示其背后迥异的融合哲学与工程取舍,为选型、微调与推理优化提供底层依据。 阅读详情

相关推荐

从网格划分到端口接地:一份给ADS新手的Momentum RF仿真避坑实操指南

本文为ADS新手提供Momentum RF仿真的实用指南,涵盖网格划分、端口接地、特殊结构处理等关键设置技巧。通过30-50 cells/λ原则、1/10波长限制等黄金法则,帮助用户平衡仿真精度与效率,避免常见错误,提升电磁仿真结果的准确性。

weixin_33692284的博客 506

java中调用c(c++)写的dll文件的实现及步骤

从网上找了这篇文档,做这个的时候感觉并不是特困难,感觉非常的新奇,毕竟自己做c语言的项目特别少.现在把这篇文章转载过来,加了自己的一些注意项。JNI使用技巧点滴 本文为在 32 位 Windows 平台上实现 Java 本地方法提供了实用的示例、步骤和准则。本文中的示例使用 Sun Microsystems 公司创建的 Java Development Kit (JDK) 版本 1.4

oceanrock的专栏 4874

【C语言基础】野指针与空指针

全网最接地气的C语言野指针介绍,此处对于野指针与空指针知识点做一些简要的介绍,作者实属初学,写博客也是作者学习的一个过程,难免文章中有内容理解不到位或者有不当之处,还请朋友们不吝指正,希望大家多多给予支持,赠人玫瑰,手有余香! 文章目录一:野指针1.1 :野指针的成因2.1 :规避野指针二:空指针 一:野指针 概念:野指针就是指向的内存地址是未知的(随机的,不正确的,没有明确限制的)。 说明:指针变量也是变量,是变量就可以任意赋值。但是,任意数值赋值给指针变量没有意义,因为这样的指针就成了野指针,此指针指向

qq_43727529的博客 2万+

JNI学习积累之三 - 操作JNI函数以及复杂对象传递

链接库 (windos下就是.dll库,Linux就是.so库了,不懂在Window下生成dll动态库的,具体流程可看我的这篇博客:    《Android中JNI的使用之一:Java原生JNI的使用、javah指令的使用以及图解教材》)。即可掌握JNI的使用了了。         总的来说,JNI是不难的。通过前面的学习相信你应该有所了解。今天,我们从几个简单的小例子,来对JNI进

kevin_hcy的专栏 6370

DIY电磁炉核心驱动方案:IR2153PBF自振荡半桥芯片实战指南(附电路图)

本文详细介绍了IR2153PBF自振荡半桥驱动芯片在DIY电磁炉核心驱动方案中的实战应用。该芯片集成了振荡器与600V高压驱动能力,仅需少量外围元件即可生成互补带死区的PWM信号,极大简化了半桥逆变电路设计。文章深入解析了其工作原理、关键参数,并提供了完整的电路设计、PCB布局指南及调试步骤,帮助电子爱好者构建稳定高效的感应加热驱动核心。

beer8的博客 593

【机器学习】随机森林(Random Forest,简称 RF):预测光伏电站功率 || 缺失数据处理 || 重复行处理...

【机器学习】随机森林(Random Forest,简称 RF):预测光伏电站功率。

追光者♂:记录、分享、总结、提升,现象级专栏《Python从入门到人工智能》作者,无惧黑暗,坚信曙光 1652

Java进阶:JNI使用技巧点滴积累

本文为在 32 位 Windows 平台上实现 Java 本地方法提供了实用的示例、步骤和准则。本文中的示例使用 Sun Microsystems 公司创建的 Java Development Kit (JDK) 版本 1.4.1。用 C 语言编写的本地代码是用 Microsoft Visual C++ 编译器编译生成。    简介  近日,由于项目需要,要在WEB页面实现图像转换功能,而VC在图

iefoahz3802的专栏 434

SPICE仿真软件:PSpice_(10).噪声分析

噪声分析是电路设计和优化中的一个重要工具,特别是在低噪声放大器、传感器电路和通信电路中。通过准确设置噪声源和仿真参数,合理选择频率范围,并验证仿真结果,可以有效地评估和优化电路的噪声性能。PSpice提供的噪声分析功能强大且灵活,能够帮助工程师和研究人员在多种应用场景下进行详细的噪声分析。

kkchenjj的博客 1538

JNI使用技巧点滴(二)

 作者:normalnotebook 背景上一讲我们介绍了JNI的基本概念和基本用法。现在介绍复杂一点的例子,用JNI调用其他工具生成的DLL,实现某个特定的功能。在这里我们将用VC编写一个DLL,供JAVA调用。 VC编写简单DLL这个DLL实现一个简单的字符串传递,然后弹出一个消息框,显示所传递的字符串,同时将所传递的字符串变成小写,返回给JAVA程序。即JAVA程序和VC

百年孤独 1050

x2-DFD:A framework for explainable and explainable deepfake detection

该文章提出了X2-DFD框架,用于可解释和可扩展的深度伪造检测。通过评估大型多模态语言模型(MLLMs)在深度伪造检测中的内在能力,发现它们在不同伪造相关特征上的有效性各异。基于此,实施了针对性的微调策略,显著提高了MLLMs的解释能力,并整合了外部深度伪造检测器(EDDs),以结合MLLMs和传统检测器的互补优势,实现更好的检测和解释。

志在山顶的人,不会贪念山腰的风景 510

【嵌入式DIY实例-ESP32篇】-热成像仪

在本文中,我们将使用 MLX90640 热像仪和 1.8 英寸 ST7735 TFT 显示屏,构建一款基于 ESP32 的高性能紧凑型热像仪。本项目旨在打造一款便携、响应迅速的热像仪,具有增强的图像质量、优化的帧率和精准的温度读数。

视觉与物联智能 880

JNI使用技巧点滴(二)

作者:normalnotebook 背景上一讲我们介绍了JNI的基本概念和基本用法。现在介绍复杂一点的例子,用JNI调用其他工具生成的DLL,实现某个特定的功能。在这里我们将用VC编写一个DLL,供JAVA调用。 VC编写简单DLL这个DLL实现一个简单的字符串传递,然后弹出一个消息框,显示所传递的字符串,同时将所传递的字符串变成小写,返回给JAVA程序。即JAVA程序和VC编写的

极光 1976

QML实现ListView的拖动排序

现有一种需求,就是用鼠标拖动某项,动态去改变某一项在ListView中显示的顺序位置,经过研究及实践实战,实现方式的核心代码如下: import QtQuick 2.4 import QtQuick.Controls 1.3 import QtQuick.Window 2.2 import QtQuick.Dialogs 1.2 Rectangle { width: 800 ...

草上爬的博客 7564

Java进阶:JNI使用技巧点滴

本文为在 32 位 Windows 平台上实现 Java 本地方法提供了实用的示例、步骤和准则。本文中的示例使用 Sun Microsystems 公司创建的 Java Development Kit (JDK) 版本 1.4.1。用 C 语言编写的本地代码是用 Microsoft Visual C++ 编译器编译生成。    简介    近日,由于项目需要,要在WEB页面实现图像转换功能,而VC

1189

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

(转)程序员进阶必读篇:JNI使用技巧点滴

作者:http://www.chinaaspx.com 发文时间:2005.06.20近日,由于项目需要,要在WEB页面实现图像转换功能,而VC在图像转换方面有着得天独厚的优势。我们首先用VC封装出图像转换的DLL,然后用JAVA的本地化方法JNI调用用于图像转换的DLL,最后用JavaBean调用JNI生成的DLL。一、JAVA部分1.无包的情况:实例一:public class MyNativ

ROC的专栏 1360

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

使用NDK移植开源项目,JNI的使用技巧

第一步://找到对应的java 类(对象)第二步://通过取到的java类(对象)创建一个指定固定大小的数组第三步:”);//找到对象中的列注意:在JNI中并未提供jstring 类型的对象,所以必须通过L指定包名找到该类,在有提供的类型中,可以直接使用该类型的大写首字母(jlong 需使用J)如jint 类型可以如此编写:对应的JNI提供类型第四步://""代表可以访问默认构造函数//通过第一步找到的jclass创建对应的对象第五步://为对象中的每一列赋值。

2401_84520401的博客 783

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

JNI常用开发技巧

讲讲JNI常用技能

qq_37841321的博客 2546

JNI及使用流程

JNI介绍及使用流程

linwq8的博客 1670

android中jni详细,Android中的JNI使用简介

一、本文说明本文不对Android工程的各种配置做说明,只是简单介绍下开发过程中如何进行C与Java互相调用以及出现异常情况的处理。二、NDK简介Android NDK 是一套允许您使用 C 和 C++ 等语言,以原生代码实现部分应用的工具集。在开发某些类型的应用时,这有助于您重复使用以这些语言编写的代码库。三、JNI简介JNI是Java Native Interface的缩写,它提供了若干的AP...

weixin_34677884的博客 6763

【JNI编程】JNI数组使用

我们经常遇到在native代码中处理数组的需求,JNI中数组的使用可以说是基本功。下面的例子演示了如何在JNI中获取数组的长度,JNI获取Java层的数组并使用等。 一、涉及API 1.1 GetArrayLength jsize GetArrayLength(JNIEnv *env, jarray array); 返回数组中元素的数量。 LINKAGE: JNIEnv接口函数表中的索引171。...

洪伟的专栏 2195

使用JNI总结

使用JNI总结和参考

GeiGe123的博客 929

Jni使用小结

什么是JNI 3 1.1. JNI 编程中的优点 3 1.2. JNI 编程中的弊端 3 1.3. Jni加载方法 3 Java、Jni、C之间的数据类型对应关系 4 2.1. 基本类型 4 2.2. 数组类型 4 2.3. 对象类型 5 2.4. 方法的签名 5 JNI中JNIEnv、jobject和jclass是什么? 6 3.1. JNIEnv指针 6 3.1.1. 常用的Jni函数列表 8 3.2. Jni接口参数jobject和jclass的区别 11 常用的Jni函数说明 12 4.1. 获得.

huangling07031190的专栏 1174
上一篇: VC++ MFC 常用技巧 (一)
下一篇: java 异常处理学习笔记
normalnotebook
博客等级 码龄24年 647粉丝 38原创
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值