一、java JNI 调用动态库
1、在MyEclipse 中创建一个test的web工程
2、在工程下创建一个class文件 package名为JNI ,类名test
3、在test下面定义一个方法
package JNI; public class getCPUID { //定义一个方法 该方法是在dll中实现 public native static String getcpuID(); static { System.loadLibrary( "getCPUID" ); //加载dll库 } }
4、发布该web 程序(目的是把test类编译成class文件,你也可以直接用编译工具编译该clss文件)
5、 将在发布后的文件中找到该 JNI文件夹 ,复制该文件夹所在路径(发布的是放在resin)
D:\yys\resin-pro-3.1.7a\deploy\test2\WEB-INF\classes\JNI
6、打开dos命令行 输入cd D:\yys\resin-pro-3.1.7a\deploy\test2\WEB-INF\classes\
(如果cd 目录没变,那在后面在 输入 d: 回车 一般不会出先这种问题 ,但是我很幸运的 遇到了)
7、javah JNI.getCPUID 此时生成JNI_getCPUID.h头文件
8、创建一个空的win32 dll项目 ,我这用的是vs2008 visual c++ win32项目 空项目 名称
getCPUID(注 这个要与System.loadLibrary( "getCPUID" ); //加载dll库中名称一致)
9、分别把java安装路径下 C:\Program Files\Java\jdk1.5.0_06\include 文件夹中的 jni.h 与
C:\Program Files\Java\jdk1.5.0_06\include\win32 jin_md.h 及先前生成的JNI_getCPUID.h
拷贝到c++项目的工程目录下。
10、把刚拷贝过来的头文件添加到项目的头文件夹中
11、创建一个 getCPUID.cpp文件 在该文件添加如下代码
#include "JNI_getCPUID.h" #include <stdio.h> #include <stdlib.h> #include <string.h> //汇编获取 cpu编号 int getCPUID(char * cpuid) { unsigned long s1,s2,s3,s4; unsigned long s11,s22,s33,s44; char p1[128]; char p2[128]; char p3[128]; char p4[128]; unsigned int eax = 0; unsigned int ebx,ecx,edx; __asm { mov eax, 1; cpuid ; mov s1, eax mov s2, ebx mov s3, ecx mov s4, edx } s11=s1; s22=s2; s33=s3; s44=s4; //这里犹豫cpu 真实的序列号在p4之后就被禁止使用只能取到第32 processorID sprintf(cpuid, "%08X%08X", s44,s11); return 0; } //char 转 jstring jstring stoJstring(JNIEnv* env, char* pat) { jclass strClass = env->FindClass("Ljava/lang/String;"); jmethodID ctorID = env->GetMethodID(strClass, "<init>", "([BLjava/lang/String;)V"); jbyteArray bytes = env->NewByteArray(strlen(pat)); env->SetByteArrayRegion(bytes, 0, strlen(pat), (jbyte*)pat); jstring encoding = env->NewStringUTF("utf-8"); return (jstring)env->NewObject(strClass, ctorID, bytes, encoding); } //数据类型转换 JNIEXPORT jstring JNICALL Java_JNI_getCPUID_getcpuID (JNIEnv * env, jclass js) { char cpuid[40]; getCPUID(cpuid); return stoJstring(env,cpuid); }
12、修改JNI_getCPUID.h 文件的<jni.h> 把<>改为“” 否则 会包找不到头文件错误。
13、编译项目把生成的 getCPUID.dll 拷贝到任何一个换件变量path 路劲下就可以 我这拷贝到
C:\Program Files\Java\jdk1.5.0_06\bin 文件夹下
14、做个一个是测试的jsp页面 或者 在上面的java文件的类后面 加一个 main方法进行测试 加完mian如下
package JNI; public class getCPUID { //定义一个方法 该方法是在dll中实现 public native static String getcpuID(); static { System.loadLibrary( "getCPUID" ); //加载dll库 } public static void main(String[] args) { //yysLic u=new yysLic(); @SuppressWarnings("unused") String ls_cpuID=getCPUID.getcpuID(); } }
调试 查看 ls_cpuID 变量的值
15、在写jni代码是常用的 java与c++类型转换的 方法(注 int 不需要手动转能自动转换)
//char * 转java的jstring
jstring stoJstring(JNIEnv* env, char* pat) { jclass strClass = env->FindClass("Ljava/lang/String;"); jmethodID ctorID = env->GetMethodID(strClass, "<init>", "([BLjava/lang/String;)V"); jbyteArray bytes = env->NewByteArray(strlen(pat)); env->SetByteArrayRegion(bytes, 0, strlen(pat), (jbyte*)pat); jstring encoding = env->NewStringUTF("utf-8"); return (jstring)env->NewObject(strClass, ctorID, bytes, encoding); } //
//jstring 转 char*
//jstring to char* char* jstringTostring(JNIEnv* env, jstring jstr) { char* rtn = NULL; jclass clsstring = env->FindClass("java/lang/String"); jstring strencode = env->NewStringUTF("utf-8"); jmethodID mid = env->GetMethodID(clsstring, "getBytes", "(Ljava/lang/String;)[B"); jbyteArray barr= (jbyteArray)env->CallObjectMethod(jstr, mid, strencode); jsize alen = env->GetArrayLength(barr); jbyte* ba = env->GetByteArrayElements(barr, JNI_FALSE); if (alen > 0) { rtn = (char*)malloc(alen + 1); memcpy(rtn, ba, alen); rtn[alen] = 0; } env->ReleaseByteArrayElements(barr, ba, 0); return rtn; }
16、犹豫java不能直接获取电脑硬件信息通过该方法能获取到 电脑的信息也能通过该方法对公司的一些核心代码算法
进行加密 软件论证等 这都是比较好用 。