`

Java调用dll详细过程(JNI)

    博客分类:
  • Java
阅读更多

最近项目有这样一个需求,在已有的CS软件中添加一个链接,将当前登录用户的用户名加密后放在url地址中,在BS的login方法里通过解密判断,如果为合法用户则无需再次登录直接进入平台,CS软件方提供了一个加密解密的dll文件,我们需要在action中通过该dll解密,那么就涉及到java调用dll的问题。

首先我选择了JNI方式(因为网上说的另两种方式Jawin, Jacob更不会),大体流程如下:

1、写一个java的class,在类里声明所调用的库名称和需要使用的函数(注意:需要对方法做本地声明,关键字为native。且只需要声明,而不需要具体实现)

 

package com;
public class javacall
{
        static
        {
                System.loadLibrary("htgsjencrypt");
        }
       
        public native static String DecodeString(char[] szSrc);
        public native static String EncodeString(char[] szSrc);

        private static void printCharArray(char[] content)
        {
        	String temp=new String(content);
        	System.out.println(temp);
        }
        public static void main(String[] args)
        {
          String s="123";
          char[] src=new char[100];
          src=s.toCharArray();
          String encode="";
          printCharArray(src);
          encode=javacall.EncodeString(src);
          System.out.println("encode="+encode);
          String decode="";
          src=encode.toCharArray();
          decode=javacall.DecodeString(src);
          System.out.println("decode="+decode);
          
        }
}
 

这个地方需要提一下,新建这个class时最好不要建在默认包中,将来对这个工程打包后,在引用的工程中无法找到默认包中的class(也许是我写的不对,不过写在默认包中确实会带来不必要的麻烦)

2、对于以上编译好的class文件通过使用javah命令生成头文件javacall.h,这个文件需要被C++程序调用来生成所需的库文件

/* DO NOT EDIT THIS FILE - it is machine generated */
#include "jni.h"
/* Header for class com_javacall */

#ifndef _Included_com_javacall
#define _Included_com_javacall
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     com_javacall
 * Method:    DecodeString
 * Signature: ([C)Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_com_javacall_DecodeString
  (JNIEnv *, jclass, jcharArray);

/*
 * Class:     com_javacall
 * Method:    EncodeString
 * Signature: ([C)Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_com_javacall_EncodeString
  (JNIEnv *, jclass, jcharArray);

#ifdef __cplusplus
}
#endif
#endif

 这里需要提到一点,默认生成的头文件中写的是

#include <jni.h>

在C++的calss中引用时编译报错找不到jni.h,可以去jdk安装包的include文件夹中拷贝jni.h、jni_md.h、jawt_md.h三个文件到程序目录,这时再编译可能还报找不到jni.h的错误,可以将#include <jni.h>改为#include "jni.h",因为前者是引用系统头文件的写法

3、在VC中新建一个库文件htgsjencrypt,在新建的class文件中实现java头文件中声明的两个加密解密方法,因为第三方没有提供.lib文件,也没有.h文件,那么只能用动态使用链接库的方式来调用dll了,具体代码如下:

#include "gsjencrypt.h"
#include "com_javacall.h"
#include "windows.h"
#include <iostream>
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

gsjencrypt::gsjencrypt()
{

}

gsjencrypt::~gsjencrypt()
{

}
typedef int (WINAPI *FDecodeString)(char szSrc[100], char szDest[100]);
typedef int (WINAPI *FEncodeString)(char szSrc[100], char szDest[100]); 

JNIEXPORT jstring JNICALL Java_com_javacall_EncodeString(JNIEnv * env, jclass jobject, jcharArray src)
{
	HINSTANCE hDLL;
    hDLL=LoadLibrary("gsjencrypt.dll");//加载动态链接库gsjencrypt.dll文件;
	if(hDLL==NULL)
		return 0;
	FEncodeString encodeString=(FEncodeString)GetProcAddress(hDLL,"EncodeString");
	jsize size = (env)->GetArrayLength(src);

	jchar * arrayBody = (env)->GetCharArrayElements(src,0); 
	//char * csrc=(char *)arrayBody;
	
	char csrctemp[100]="";
	int k=0;
	while(size!=0)
	{
		csrctemp[k]=*arrayBody;
		*arrayBody++;
		size--;
		k++;
	}
	char cdesttemp[100]="";
	encodeString(csrctemp,cdesttemp);
	(env)->ReleaseCharArrayElements(src,arrayBody,0);
	return (env)->NewStringUTF(cdesttemp);
}
JNIEXPORT jstring JNICALL Java_com_javacall_DecodeString(JNIEnv * env, jclass jobject, jcharArray src)
{
	HINSTANCE hDLL;
    hDLL=LoadLibrary("gsjencrypt.dll");//加载动态链接库gsjencrypt.dll文件;
	if(hDLL==NULL)
		return 0;
	FDecodeString decodeString=(FDecodeString)GetProcAddress(hDLL,"DecodeString");
	jsize size = (env)->GetArrayLength(src);
    jchar * arrayBody = (env)->GetCharArrayElements(src,0); 
	char * csrc=(char *)arrayBody;
	char csrctemp[100]="";
	int k=0;
	while(size!=0)
	{
		csrctemp[k]=*arrayBody;
		*arrayBody++;
		size--;
		k++;
	}
    //arrayBody=(env)->GetCharArrayElements(dest,0); 
    //char * cdest=(char *)arrayBody;
    char cdesttemp[100]="";
	decodeString(csrctemp,cdesttemp);
	(env)->ReleaseCharArrayElements(src,arrayBody,0);
	return (env)->NewStringUTF(cdesttemp);
}

  这里需要注意的是

typedef int (WINAPI *FDecodeString)(char szSrc[100], char szDest[100]);
typedef int (WINAPI *FEncodeString)(char szSrc[100], char szDest[100]); 

以上两个方法是原始dll中提供给外界调用的函数接口,声明时一定要记得加WINAPI,否则调用时始终报错。

4、最后将第三方提供的gsjencrypt.dll和新生成的htgsjencrypt.dll同时拷贝到java.library.path里(jdk或者jre的bin文件中),然后将最开始写的java程序打包即可被别的工程调用。

记录一下最难解决的问题,就是不知道怎样在c++中返回给java解密后的串,因为总是想把指针的概念与java中的某个byte数组或者char数组关联起来,始终不能成功,最后尝试使用NewStringUTF才解决问题,哎,C++已经六年没用过了,真是费劲啊

1
0
分享到:
评论

相关推荐

    JAVA项目JNI调用dll实现DEMO源码,C++&JAVA

    完整的实现java跨平台调用C程序源码,包含JAVA源码和C源码以及编译后的demo dll。将dll放到jdk bin目录下,java 项目可以直接运行。若要修改dll可以,修改C源码后重新编译生成dll。该demo处理了多线程调用c,全局...

    JAVA通过JNI调用C#dll的整个项目工程

    在C#环境中,使用Visual Studio或其他开发工具创建一个新的类库项目,编写需要被Java调用的公共方法。编译完成后,生成的DLL文件将包含可供其他程序使用的函数。 3. **JNI头文件生成**: 使用Java的`javah`工具,...

    JAVA如何调用dll:用JNI调用C或C++动态联接库

    Java 调用DLL(动态链接库)主要是通过JNI(Java Native Interface)技术来实现的。JNI是Java平台标准的一部分,允许Java代码和其他语言写的代码进行交互。在本例中,我们将详细介绍如何使用JNI调用C或C++编写的DLL...

    JAVA如何调用dll:用JNI调用C或C++动态联接库原来如此简单

    下面将详细介绍如何使用JNI来调用DLL,并解释相关知识点。 1. **JNI简介** JNI是Java平台的标准部分,提供了一组接口,使得Java代码能够调用本地代码(如C和C++),反之亦然。JNI接口包括了各种函数,让开发者可以...

    Java调用动态链接库(Java 调用 DLL)

    在实际项目中,Java调用DLL通常用于利用已有的C/C++库,或者执行一些Java不擅长的任务,如硬件控制、图形处理等。然而,由于涉及到本地代码,这也会增加程序的复杂性和维护难度,因此在选择这种方法时需要权衡利弊。...

    Java通过JNI调用DLL动态库

    Java通过JNI调用DLL动态库,亲测试编写

    JAVA调用DLL方法 JAVA调用DLL方

    ### JAVA调用DLL方法 在跨平台开发领域中,Java作为一种强大的编程语言,因其具有良好的移植性和跨平台性而被广泛使用。然而,在某些特定情况下,我们可能需要调用本地库(例如DLL文件)来实现特定功能或提高性能。...

    Java调用dll示例

    总结来说,Java调用DLL主要涉及JNI的使用,包括在Java中声明native方法,生成JNI头文件,编写C++代码实现接口,编译链接DLL,以及在Java中加载和调用DLL。这个过程允许Java开发者充分利用C++的高性能特性,同时保持...

    JAVA JNI调用DLL完整步骤

    总结,Java调用DLL的完整步骤包括:定义Java的`native`方法,使用`javah`生成头文件,编写C/C++ DLL代码,编译DLL,最后在Java程序中调用。这个过程可能需要对JNI规范有深入理解,以及一定的C/C++编程基础。通过熟练...

    Java调用DLL源代码

    Java调用DLL是Java开发中一个重要的技术主题,它允许Java程序与本地操作系统API或者其他C/C++编写的动态链接库进行交互。在Java中,有多种方法可以实现这个功能,其中最常用的是Java Native Interface (JNA) 和 ...

    java调用dll新

    总结,Java调用C++ DLL的过程主要包括:编写C++ DLL、创建Java JNI接口、生成JNI头文件、实现JNI接口并编译为DLL、最后在Java程序中加载和调用DLL。这个过程虽然有些复杂,但能充分利用现有C++库,拓展Java的功能。...

    jni_java_dll_jsp.zip_Java调用dll_applet_java Applet_java dll jsp_j

    Java调用DLL文件是将Java程序与C/C++编写的动态链接库进行交互的技术,主要应用于需要利用非Java原生功能或与已有C/C++库集成的场景。本资料包"jni_java_dll_jsp.zip"提供了关于这个主题的详细资料,特别是针对...

    Java通过JNI调用C++的DLL文件.docx

    Java 通过 JNI 调用 C++ 的 DLL 文件 JNI(Java Native Interface)是一种允许 Java 代码和本地应用程序交互的技术。通过 JNI,Java 应用程序可以调用本地库,反之亦然。本文将详细介绍如何使用 JNI 将 Java 应用...

    GMSSL的java调用(JNI库和调用实例).zip

    在这个“GMSSL的java调用(JNI库和调用实例).zip”压缩包中,我们主要探讨如何在Java环境中通过JNI(Java Native Interface)来调用GMSSL库,以便利用这些国密算法进行数据加解密和哈希运算。 首先,我们需要了解...

    JNI实例 Java调用DLL c++调用Java

    总之,JNI实例“Java调用DLL c++调用Java”是一个实用的学习资源,它详细解释了如何利用JNI进行Java与C++的交互,无论是将本地库引入Java程序还是将Java功能嵌入C++应用。通过实践这些例子,开发者能够深入理解JNI的...

    Java调用dll(JNI调用C或C++动态联接库)

    JAVA如何调用dll:用JNI调用C或C++动态联接库原来如此简单.doc

    java调用DLL文件

    总结来说,Java调用DLL文件主要依赖于JNative库,通过定义Java接口、加载DLL、获取函数句柄、创建代理对象以及调用函数等步骤实现。这种方法使得Java开发者能够充分利用C/C++库的功能,同时也保持了Java的跨平台特性...

    亲测可用,java 成功调用dll函数。包含调用回调函数,springboot版本。最近由于公司业务需要,要调用dll文件,用JNA调用。

    Java调用DLL函数是跨平台编程中的一种常见需求,特别是在Java与C/C++代码交互时。JNA(Java Native Access)是Java平台上的一个库,它允许Java代码直接调用本机库(如DLL文件)的函数,而无需编写JNI(Java Native ...

    java调用dll接口

    总结来说,Java调用DLL接口是一个结合了JNA库和适当编程技巧的过程,它使得Java开发者能够充分利用操作系统级别的功能,而无需离开Java的舒适区。这种技术在处理低级操作、硬件控制、系统调用等场景时特别有用。通过...

    C++库封装JNI接口-实现java调用c++

    总结,C++库封装JNI接口实现Java调用C++涉及的主要步骤包括:声明Java中的本地方法,生成JNI头文件,编写C++实现,编译成库,最后在Java中加载并调用。这个过程需要理解Java和C++之间的数据类型转换,以及如何在两种...

Global site tag (gtag.js) - Google Analytics