jni编程实现(windows)(代码片段)

fishbay fishbay     2023-01-26     601

关键词:

上一篇介绍了Linux平台的JNI编程方法,Windows平台的JNI本地调用基本类似,区别就是制作的动态库不同,Linux平台是*.soWindows平台是*.dll。其中,Windows平台的函数库也分为静态库和动态库,下面介绍一下相关概念:

静态库
在链接步骤中,连接器将从库文件取得所需的代码,复制到生成的可执行文件中,这种库称为静态库。其特点是可执行文件中包含了库代码的一份完整拷贝;缺点就是被多次使用就会有多份冗余拷贝。即静态库中的指令都全部被直接包含在最终生成的EXE文件中了。在vs中新建生成静态库的工程,编译生成成功后,只产生一个*.lib文件

动态库
动态链接库是一个包含可由多个程序同时使用的代码和数据的库,DLL不是可执行文件。动态链接提供了一种方法,使进程可以调用不属于其可执行代码的函数。函数的可执行代码位于一个DLL中,该DLL包含一个或多个已被编译、链接并与使用它们的进程分开存储的函数。在vs中新建生成动态库的工程,编译成功后,产生一个.lib文件和一个.dll文件

那么静态库中的lib和动态库中的lib究竟有什么区别呢?

静态库中的lib:该lib包含函数代码本身(即包括函数的索引,也包括实现),在编译时直接将代码加入程序当中

动态库中的lib:该lib包含了函数所在的dll文件和文件中函数位置的信息(索引),函数实现代码由运行时加载在进程空间中的dll提供

本文制作动态库,即生成*.lib*.dll文件,使用Visual Studio 2017工具,步骤和linux平台的类似,下面详细介绍

制作动态库

1.编写native声明方法的java类

编写Java类,声明一个native的本地方法

public class Hello 
    public native static String sayHello(String name);

    static 
        System.load("E:\\Eclipse\\Hello\\libhello.dll");
    

    public static void main(String[] args) 
        Hello hello = new Hello();
        String ret = hello.sayHello("kelvin");
        System.out.println(ret);
    

2.编译java类

使用javac进行编译

#javac Hello.java

3.生成本地文件*.h

使用javah生成Hello.h头文件,依赖上一步的Hello.class

# javah -jni Hello

4.使用Visual Studio 2017创建构建动态库

接下来,使用Visual Studio 2017制作动态库libhello.liblibhello.dll

a、新建工程

首先,新建工程,文件 -> 新建 -> 项目 -> Visual C++ -> Windows 桌面 -> 动态链接库(DLL)

技术分享图片

b、添加头文件

把生成的本地头文件Hello.h导入到工程中;另外,还需要把jni.hjni_md.h这两个头文件也导入到工程中

c、编写本地方法的实现

新增Hello.cpp文件,编码实现本地方法

#include "stdafx.h"
#include <iostream>
#include "Hello.h"

using namespace std;

JNIEXPORT jstring JNICALL Java_Hello_sayHello(JNIEnv *env, jclass jc, jstring name)

    const char *buf =  0 ;
    buf = env->GetStringUTFChars(name, NULL);

    cout << buf << endl;

    return env->NewStringUTF("hello");
d、生成动态库

编译工程,生成动态链接库。如果是64位系统,还需要设置Debugx64,否则会报错

生成 -> 重新生成解决方案

设置为64位系统的动态库

技术分享图片

5、调用动态库

把工程的根目录下Debug中的libhello.dll拷贝到Hello.class目录,如果是x64则是在目录x64目录下;然后,调用Hello测试jni的本地调用

# java -classpath E:EclipseHello Hello
kelvin
hello

看到输出,表明了libhello.dll被正常加载调用了


这就是Windows的本地调用,虽然Java程序中提倡单一语言风格,但是本地调用提供了一种解决方案,在Java语言无法实现时,选择使用jni也是一种合适的方式。

参考资料

java native方法与JNI实现
lib 和 dll 的区别、生成以及使用详解




android中的jni和ndk编程实践(代码片段)

Android中的JNI开发JNI即JavaNativeInterface(b),该接口使得java可以方便的调用C、C++等本地代码,弥补了因跨平台而受到的本地交互能力弱化问题。本文开发环境:系统:Windows8.164IDE:IntellijIDEAJNI开发流程:1、在... 查看详情

jni的基本使用一(代码片段)

...a语言也是通过JNI接口来调用系统的功能,只不过JNI的实现部分在JDK中,这样可以增加Java的功能。同样用户程序也可以通过实现JNI接口来调用本地方法。如:如:windows和linux上Java程序需要调用外设驱动,就需要使用JNI... 查看详情

jni的基本使用一(代码片段)

...a语言也是通过JNI接口来调用系统的功能,只不过JNI的实现部分在JDK中,这样可以增加Java的功能。同样用户程序也可以通过实现JNI接口来调用本地方法。如:如:windows和linux上Java程序需要调用外 查看详情

混合编程jni第七篇之jni的命令行们(代码片段)

 系列目录:【混合编程Jni】系列目录_香菜聊游戏的博客-CSDN博客        今天将继续JNI的学习,jni编程中常使用的一些命令行工具如何使用事半功倍,今天就快速的过一下,希望在接下来的使用中... 查看详情

混合编程jni第五篇之c++访问java代码(代码片段)

 系列目录:【混合编程Jni】系列目录_香菜聊游戏的博客-CSDN博客今天继续JNI的学习,因为是混合编程,所以在写的过程中需要进行交互Java可以调用C++,C++也可以调用Java,虽然作为Java程序很少写C++,但是既然是做JNI开发,就... 查看详情

[rk3568][android11]jni调用流程分析(代码片段)

...允许java代码和用其它语言编写的代码进行交互.JNI是本地编程接口,它使得在Java虚拟机(VM)内部运行的Java 查看详情

[rk3568][android11]jni调用流程分析(代码片段)

...允许java代码和用其它语言编写的代码进行交互.JNI是本地编程接口,它使得在Java虚拟机(VM)内部运行的Java 查看详情

混合编程jni第八篇之jni对虚拟机的操作(代码片段)

写了好多了,今天继续写一下对虚拟机的一些操作。创建虚拟机jintJNI_CreateJavaVM(JavaVM**p_vm,void**p_env,void*vm_args);加载并初始化一个JavaVM,并返回一个指向JNI接口指针的指针。调用的线程JNI_CreateJavaVM()被认为是 主线程。不支持在... 查看详情

jni初级接触(代码片段)

...c;它允许Java代码和其他语言写的代码进行交互。JNI是本地编程接口,它使得在Java虚拟机(VM)内部运行的Java代码能够与用其它编程语言(如C、C++和汇编语言)编写的应用程序和库进行交互操作。Andoird 查看详情

jni初级接触(代码片段)

...c;它允许Java代码和其他语言写的代码进行交互。JNI是本地编程接口,它使得在Java虚拟机(VM)内部运行的Java代码能够与用其它编程语言(如C、C++和汇编语言)编写的应用程序和库进行交互操作。Andoird 查看详情

在windows平台借助cmake编译jni(代码片段)

依赖jdkvisualstudio(只需安装cl即可)(备注:我使用的是VisualStudioCode作为代码编辑工具,当然也可以使用txt或vim等其它文本编辑工具)步骤创建Java类文件mkdirprojectDir&cdprojectDirmkdirjava&cdjavamkdirsimen 查看详情

intellijidea平台下jni编程—字符串数组(代码片段)

转载请注明出处:【huachao1001的专栏:http://blog.csdn.net/huachao1001/article/details/54407327】在前面HelloWorld篇中,自动生成的头文件对本地方法声明的形参列表中的第一个参数即为JNIEnv*。那么JNIEnv到底能用来做什么?初学... 查看详情

混合编程jni第七篇之jni的命令行们(代码片段)

...       今天将继续JNI的学习,jni编程中常使用的一些命令行工具如何使用事半功倍,今天就快速的过一下,希望在接下来的使用中可以发挥效果    javahjavah是Java提供的生成jni头文件的命令... 查看详情

混合编程jni第八篇之jni对虚拟机的操作(代码片段)

 系列目录:【混合编程Jni】系列目录_香菜聊游戏的博客-CSDN博客写了好多了,今天继续写一下对虚拟机的一些操作。创建虚拟机jintJNI_CreateJavaVM(JavaVM**p_vm,void**p_env,void*vm_args);加载并初始化一个JavaVM,并返回一个指向JNI接口指... 查看详情

混合编程jni第六篇之native中字符串和数组的操作(代码片段)

 系列目录:【混合编程Jni】系列目录_香菜聊游戏的博客-CSDN博客继续JNI的知识点,今天看下字符串和数组的一些操作这两个是比较特殊的存在字符串操作编码格式Java默认使用Unicode编码,C/C++默认使用UTF编码在本地代码中操... 查看详情

混合编程jni第四篇之引用和异常(代码片段)

继续写JNI的知识点上篇基本上介绍了数据的转换以及方法签名的相关知识点,不懂的可以看看之前的文章建议循序渐进,不可冒进今天继续介绍JNI的知识点 除八种基本数据类型之外的都是引用数据类型;关于引用Java虚拟... 查看详情

windows核心编程_hooksocket实现封包拦截(代码片段)

Socket的HOOK技术是目前网络拦截程序的基础功能,还有浏览器的抓包工具都是通过拦截Socket函数实现的浏览器也好,通讯软件也好,他们只是使用的通讯协议不一样,其最底层的全部都是通过封装Socket里的TCP/UDP实... 查看详情

intellijidea平台下jni编程全解(代码片段)

文章目录1、前言2、搭建gcc编译环境3、编写Java代码4、一键生成头文件5、编写C程序并一键生成dll(so或dylib)6、运行JNIDemo.java1、前言众所周知,Java语言是基于虚拟机的解释性语言(Java代码经过编译器编译之后并不是能够直... 查看详情