java调用动态库dll详细示例代码

 更新时间:2026年02月08日 10:00:57   作者:市场部需要一个软件开发岗位  
最近应项目的需求,需要通过java调用dll动态库,于是找了一些资料,在此记录一下实现过程,这篇文章主要介绍了java调用动态库dll的相关资料,需要的朋友可以参考下

数据类型对应关系

Java TypeC Type
booleanint
bytechar
charwchar_t
shortshort
doubledouble
floatfloat
Stringchar*

JNI 调用 dll

示例

  1. 包jni中新建java文件,JniDemo.java
package jni;

public class JniDemo {
    public native static void set(int i);
    public native static int get();
}
  1. 使用javah命令生成头文件(jni_JniDemo.h)
javah jni.JniDemo
  1. vs2017创建项目 - Visual C++ - Windows 桌面 - 动态链接库(DLL)
    新建项目JniDemo
    注:选错了工程类型报错(UnsatisfiedLinkError: dll: 此操作仅在应用容器上下文中有效。)

  2. 拷贝jni_JniDemo.h,jni.h,jni_md.h至vs工程cpp文件目录下
    jni.h在D:\Java\jdk1.8.0_111\include\jni.h
    jni_md.h在D:\Java\jdk1.8.0_111\include\win32\jni_md.h

  3. 编辑文件
    修改文件jni_JniDemo.h:

#include <jni.h> 改为 #include "jni.h"

修改文件JniDemo.cpp:

#include "stdafx.h"
#include "jni_JniDemo.h"

int number = 0;

JNIEXPORT void JNICALL Java_jni_JniDemo_set
(JNIEnv *, jclass, jint i)
{
	number = i;
}

JNIEXPORT jint JNICALL Java_jni_JniDemo_get
(JNIEnv *, jclass)
{
	return number;
}
  1. 生成64位dll库
    文件位置:D:\vsrepos\JniDemo\Release\JniDemo.dll

  2. 把64位dll库拷贝至Java JniDemo项目根目录下,修改JniDemo.java

public class JniDemo {
    static{
        System.loadLibrary("JniDemo");
    }
    public native static void set(int i);
    public native static int get();

    public static void main(String[] args) {
//        System.out.println(System.getProperty("java.library.path"));
        set(100);
        System.out.println(get());
    }
}

缺点

如果有一个现有的.dll/.so文件,如果使用JNI技术调用,我们首先需要另外使用C语言写一个.dll/.so共享库,使用SUN规定的数据结构替代C语言的数据结构,调用已有的 dll/so中公布的函数。

然后再在Java中载入这个适配器dll/so,再编写Java native函数作为dll中函数的代理。

Jnative 调用 dll

Jnative是对JNI技术进行了封装,更加方便的让java去调用DLL

JNA调用dll

JNA全称Java Native Access
https://blog.csdn.net/gwd1154978352/article/details/55097376/
JNA中,它提供了一个动态的C语言编写的转发器,可以自动实现Java和C的数据类型映射。不再需要编写C动态链接库。

地址:https://github.com/java-native-access/jna

<!-- https://mvnrepository.com/artifact/net.java.dev.jna/jna -->
<dependency>
    <groupId>net.java.dev.jna</groupId>
    <artifactId>jna</artifactId>
    <version>5.3.1</version>
</dependency

JNA没办法直接调用类方法,需要将类方法“取出来”重新封装一遍。同时为了保持类的特性,每个方法增加一个参数,用于传递类对象的引用。

示例

需要定义一个接口,继承自Library 或StdCallLibrary

public interface CLibrary extends Library {
    CLibrary INSTANCE = (CLibrary)
        Native.loadLibrary((Platform.isWindows() ? "msvcrt" : "c"),
                           CLibrary.class);

    void printf(String format, Object... args);
}

搜索动态链接库路径的顺序是:先从当前类的当前文件夹找,如果没有找到,再在工程当前文件夹下面找win32/win64文件夹,找到后搜索对应的dll文件,如果找不到再到WINDOWS下面去搜索,再找不到就会抛异常了。

JNA模拟结构体

Structure 子类中的公共字段的顺序,必须与C 语言中的结构的顺序一致。否则会报错!

c:

struct UserStruct{
long id;
wchar_t* name;
int age;
};

jna:

public static class UserStruct extends Structure{
    public NativeLong id;
    public WString name;
    public int age;
    public static class ByReference extends UserStruct
implements Structure.ByReference { }
    public static class ByValue extends UserStruct implements
Structure.ByValue
{ }
}
public void sayUser(UserStruct.ByReference struct);

Structure 类有两个内部接口Structure.ByReference 和Structure.ByValue。这两个接口仅仅是标记,如果一个类实现Structure.ByReference 接口,就表示这个类代表结构体指针。

如果一个类实现Structure.ByValue 接口,就表示这个类代表结构体本身。

JNA模拟复杂结构体

c:

struct CompanyStruct{
long id;
wchar_t* name;
UserStruct users[100];
int count;
};

jna:

public static class CompanyStruct extends Structure{
public NativeLong id;
public WString name;
public UserStruct.ByValue[] users=new UserStruct.ByValue[100];
public int count;
}

测试代码:

CompanyStruct2.ByReference companyStruct2=new CompanyStruct2.ByReference();
companyStruct2.id=new NativeLong(2);
companyStruct2.name=new WString("Yahoo");
companyStruct2.count=10;
UserStruct.ByReference pUserStruct=new
UserStruct.ByReference();
pUserStruct.id=new NativeLong(90);
pUserStruct.age=99;
pUserStruct.name=new WString("杨致远");
// pUserStruct.write();
for(int i=0;i<companyStruct2.count;i++){
companyStruct2.users[i]=pUserStruct;
}
 
TestDll1.INSTANCE.sayCompany2(companyStruct2);

考察JNI 技术,我们发现Java 调用原生函数时,会把传递给原生函数的Java 数据固定在内存中,这样原生函数才可以访问这些Java 数据。对于没有固定住的Java 对象,GC 可以删除它,也可以移动它在内存中的位置,以使堆上的内存连续。如果原生函数访问没有被固定住的Java 对象,就会导致调用失败。

固定住哪些java 对象,是JVM 根据原生函数调用自动判断的。而上面的CompanyStruct2结构体中的一个字段是UserStruct 对象指针的数组,因此,JVM 在执行时只是固定住了CompanyStruct2 对象的内存,而没有固定住users 字段引用的UserStruct 数组。因此,造成了错误。

我们需要把users 字段引用的UserStruct 数组的所有成员也全部固定住,禁止GC 移动或者删除。

如果我们执行了pUserStruct.write();这段代码,那么就可以成功执行上述代码。

Structure 类的write()方法会把结构体的所有字段固定住,使原生函数可以访问。

总结

到此这篇关于java调用动态库dll的文章就介绍到这了,更多相关java调用动态库dll内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Java中遍历Map的多种方法示例及优缺点总结

    Java中遍历Map的多种方法示例及优缺点总结

    在java中遍历Map有不少的方法,下面这篇文章主要给大家介绍了关于Java中遍历Map的多种方法,以及各种方法的优缺点总结,文中通过示例代码介绍的非常详细,对大家具有一定的参考学习价值,需要的朋友们下面来一起看看吧。
    2017-07-07
  • Nacos封装通用HttpClient详解

    Nacos封装通用HttpClient详解

    这篇文章主要介绍了Nacos封装通用HttpClient用法,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-01-01
  • SpringData JPA中查询接口Repository的使用

    SpringData JPA中查询接口Repository的使用

    本文主要介绍了SpringData JPA中查询接口Repository的使用,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-07-07
  • Springmvc发送json数据转Java对象接收

    Springmvc发送json数据转Java对象接收

    这篇文章主要介绍了Springmvc发送json数据转Java对象接收,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-10-10
  • idea中安装VisualVM监控jvm的图文教程

    idea中安装VisualVM监控jvm的图文教程

    这篇文章主要介绍了idea中安装VisualVM监控jvm的教程,本文通过图文并茂的形式给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-09-09
  • java实现批量生成二维码

    java实现批量生成二维码

    这篇文章主要为大家详细介绍了java实现批量生成二维码的相关代码,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-05-05
  • 使用CI/CD工具Github Action发布jar到Maven中央仓库的详细介绍

    使用CI/CD工具Github Action发布jar到Maven中央仓库的详细介绍

    今天通过对Github Action的简单使用来介绍了CI/CD的作用,这个技术体系是项目集成交付的趋势,也是面试中的一个亮点技能。 而且这种方式可以实现“一次配置,随时随地集成部署”,感兴趣的朋友一起看看吧
    2021-07-07
  • 在Spring Boot项目中引入本地JAR包的步骤和配置

    在Spring Boot项目中引入本地JAR包的步骤和配置

    本文探讨了在Spring Boot项目中引入本地JAR包的步骤和必要的配置,通过使用Maven的system作用域,开发者可以将自定义的本地库或功能集成到Spring Boot应用程序中,,需要的朋友可以参考下
    2023-10-10
  • 在IDEA中配置Maven镜像的最新方法

    在IDEA中配置Maven镜像的最新方法

    这篇文章主要给大家介绍了关于在IDEA中配置Maven镜像的最新方法,Maven是一个流行的Java项目构建工具,它依赖于互联网上的Mave中央仓库来下载和管理项目依赖库,文中通过图文介绍的非常详细,需要的朋友可以参考下
    2023-11-11
  • 如何禁用IntelliJ IDEA的LightEdit模式(推荐)

    如何禁用IntelliJ IDEA的LightEdit模式(推荐)

    这篇文章主要介绍了如何禁用IntelliJ IDEA的LightEdit模式,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-04-04

最新评论