• [Java JNI] [Windows] [Visual Studio] [DLL] [UnsatisfiedLinkError]


      有时候使用 GCC for Windows 生成 DLL 动态链接库时, 由于各种原因, 即使加载了动态链接库, JVM 仍然找不到符号, 从而产生 java.lang.UnsatisfiedLinkError 错误

      所以还是使用微软自家的 VS 来生成 DLL 比较妥当, 由于 VS 命令行错综复杂, 建议使用图形界面, 下面是配置要点.

      (1) 包含 jdk 目录下的 include 和 includewin32 目录, 便于查找 jni.h 和 jni_md.h

      (2) 如使用纯 C 代码, 则包含 jni.h 前插入代码 #undef __cplusplus 可使代码提示更友好.

      配置好后, 我们来实现一个 Java native 方法.

    package pkg;
    
    public class WinMessageBox {
    	
    	/**
    	 * 弹出一个全局对话框
    	 * @param label 窗口标题
    	 * @param content 窗体内容
    	 * @return 调用结果 */
    	public static native boolean showMessageBox(String label, String content);
    
    }
    

      使用 javah.exe 来生成一个声明了 WinMessageBox 类中需要实现的 native 方法的头文件

    javah pkg.WinMessageBox
    

      得到文件 pkg_WinMessageBox.h , 使用 VS 实现它.

    /* DO NOT EDIT THIS FILE - it is machine generated */
    #include <jni.h>
    /* Header for class pkg_WinMessageBox */
    
    #ifndef _Included_pkg_WinMessageBox
    #define _Included_pkg_WinMessageBox
    #ifdef __cplusplus
    extern "C" {
    #endif
    /*
     * Class:     pkg_WinMessageBox
     * Method:    showMessageBox
     * Signature: (Ljava/lang/String;Ljava/lang/String;)V
     */
    JNIEXPORT jboolean JNICALL Java_pkg_WinMessageBox_showMessageBox
      (JNIEnv *, jclass, jstring, jstring);
    
    #ifdef __cplusplus
    }
    #endif
    #endif
    

      

    #undef __cplusplus
    #include "H:CodeEclipseWorkSpaceTESTinpkg_WinMessageBox.h"
    
    #include <Windows.h>
    #include <stdlib.h>
    #include <stdio.h>
    #include <time.h>
    
    JNIEXPORT jboolean JNICALL Java_pkg_WinMessageBox_showMessageBox(JNIEnv *env, jclass clazz, jstring label, jstring content){
    	MessageBoxW((HWND) NULL, (LPCWSTR) (**env).GetStringChars(env, content, 0), (LPCWSTR) (**env).GetStringChars(env, label, 0), MB_OK);
    	srand((UINT) time(0));
    	return rand() % 2 > 0 ? TRUE : FALSE;
    }
    

      生成项目后, 编写测试

    在这个过程中我们发现, 虽然我们需要使用动态链接库 JVM.dll 中的函数, 但是我们并不需要显式地去链接它, 这是因为我们的对 JVM 函数 的调用都是使用形参中传入的 JNIEnv 指针指向的 结构体对象指针 指向的 JNINativeInterface_ 结构体对象中的一张 函数指针表 调用的, Java 运行时会为我们打包 JVM 上下文, 并将这张表填好, 在调用本地方法时将其作为参数传入, 这样一来我们就可以在本地方法中使用表中的指针调用函数了.

      

  • 相关阅读:
    华南师范大学应用数学考研真题
    scoped引起的deep与>>>改变elementUI的样式
    7.mogodb索引
    JS的undefined与null,==与===的区别
    vue上传图片到七牛云的思路与实现
    JS用正则处理文件名
    JS使用正则匹配字符串去掉多余符号
    6.mongoDB更新操作
    SSL证书相关之后缀名笔记
    vue一些常用的语法
  • 原文地址:https://www.cnblogs.com/develon/p/8778478.html
Copyright © 2020-2023  润新知