




已阅读5页,还剩3页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
JNI完全手册(一)来自yippit 最近在公司里做了一个手机的项目,需要JAVA程序在发送短信的时候和第三方的短信服务器连接。短信接口是用C+写的。琢磨了三天,大致搞懂了JNI的主体部分。先将心得整理,希望各位朋友少走弯路。首先引用一篇文章,介绍一个简单的JNI的调用的过程。JAVA以其跨平台的特性深受人们喜爱,而又正由于它的跨平台的目的,使得它和本地机器的各种内部联系变得很少,约束了它的功能。解决JAVA对本地操作的一种方法就是JNI。 JAVA通过JNI调用本地方法,而本地方法是以库文件的形式存放的(在WINDOWS平台上是DLL文件形式,在UNIX机器上是SO文件形式)。通过调用本地的库文件的内部方法,使JAVA可以实现和本地机器的紧密联系,调用系统级的各接口方法。 简单介绍及应用如下: 一、JAVA中所需要做的工作 在JAVA程序中,首先需要在类中声明所调用的库名称,如下: static System.loadLibrary(“goodluck”); 在这里,库的扩展名字可以不用写出来,究竟是DLL还是SO,由系统自己判断。 还需要对将要调用的方法做本地声明,关键字为native。并且只需要声明,而不需要具 体实现。如下: public native static void set(int i); public native static int get(); 然后编译该JAVA程序文件,生成CLASS,再用JAVAH命令,JNI就会生成C/C+的头文件。 例如程序testdll.java,内容为: public class testdll static System.loadLibrary(goodluck); public native static int get(); public native static void set(int i); public static void main(String args) testdll test = new testdll(); test.set(10); System.out.println(test.get(); 用javac testdll.java编译它,会生成testdll.class。 再用javah testdll,则会在当前目录下生成testdll.h文件,这个文件需要被C/C+程序调用来生成所需的库文件。 二、C/C+中所需要做的工作 对于已生成的.h头文件,C/C+所需要做的,就是把它的各个方法具体的实现。然后编译连接成库文件即可。再把库文件拷贝到JAVA程序的路径下面,就可以用JAVA调用C/C+所实现的功能了。 接上例子。我们先看一下testdll.h文件的内容: /* DO NOT EDIT THIS FILE - it is machine generated */ #include /* Header for class testdll */ #ifndef _Included_testdll #define _Included_testdll #ifdef _cplusplus extern C #endif /* * Class: testdll * Method: get * Signature: ()I */ JNIEXPORT jint JNICALL Java_testdll_get (JNIEnv *, jclass); /* * Class: testdll * Method: set * Signature: (I)V */ JNIEXPORT void JNICALL Java_testdll_set (JNIEnv *, jclass, jint); #ifdef _cplusplus #endif #endif 在具体实现的时候,我们只关心两个函数原型 JNIEXPORT jint JNICALL Java_testdll_get (JNIEnv *, jclass); 和 JNIEXPORT void JNICALL Java_testdll_set (JNIEnv *, jclass, jint); 这里JNIEXPORT和JNICALL都是JNI的关键字,表示此函数是要被JNI调用的。而jint是以JNI为中介使JAVA的int类型与本地的int沟通的一种类型,我们可以视而不见,就当做int使用。函数的名称是JAVA_再加上java程序的package路径再加函数名组成的。参数中,我们也只需要关心在JAVA程序中存在的参数,至于JNIEnv*和jclass我们一般没有必要去碰它。 好,下面我们用testdll.cpp文件具体实现这两个函数: #include testdll.h int i = 0; JNIEXPORT jint JNICALL Java_testdll_get (JNIEnv *, jclass) return i; JNIEXPORT void JNICALL Java_testdll_set (JNIEnv *, jclass, jint j) i = j; 编译连接成库文件,本例是在WINDOWS下做的,生成的是DLL文件。并且名称要与JAVA中需要调用的一致,这里就是goodluck.dll 。把goodluck.dll拷贝到testdll.class的目录下,java testdll运行它,就可以观察到结果了。 -用Java操作Windows注册表Microsoft Windows 9x、Windows CE、Windows NT和Windows 2000中使用的中央分层数据库,用于存储为一个或多个用户、应用程序和硬件设备配置系统所必需的信息。Microsoft Windows 9x、Windows CE、Windows NT和Windows 2000中使用的中央分层数据库,用于存储为一个或多个用户、应用程序和硬件设备配置系统所必需的信息。注册表包含 Windows 在运行期间不断引用的信息,例如,每个用户的配置文件、计算机上安装的应用程序以及每个应用程序可以创建的文档类型、文件夹和应用程序图标的属性表设置、系统上存在哪些硬件以及正在使用哪些端口。注册表取代了 Windows 3.x 和 MS-DOS 配置文件(例如,Autoexec.bat 和 Config.sys)中使用的绝大多数基于文本的 .ini 文件。虽然几个 Windows 操作系统都有注册表,但这些操作系统的注册表有一些区别。如果您对以上的内容还不了解,那么您可能需要阅读一下这篇文章Microsoft Windows 注册表说明,可以从参考资料中找到,同时还可以找到它的英文原文Description of the Microsoft Windows registry。 如果您理解上面的内容就可以往下继续了。使用Preferences APIPreferences API并不是为访问Windows注册表而设计的,这是值得指出的一点。我们之所以会有上面的误解是由于Sun的Windows版本的JDK在实现Preferences API时使用了Windows注册表作为存储库,即我们用Preferences API存储的数据会保存到Windows注册表中,这样Preferenes API也就有了访问Windows注册表的能力。但是换到其它的平台或其它厂商的JDK实现又会怎么样呢?这个问题是和Preferences API的实现相关的,我们没有办法回答。 如果程序不关心存储库的细节,只是要找一个存放数据的地方,那么Preferences API很合适。Preferences API也是有局限的,请您考虑两个问题: 一个Java软件,这次我在Sun的JDK上运行并使用Preferences API保存了我的个人喜好,下次我在IBM的JDK上运行,这时我的个人喜好还可以通过Preferences API得到吗?可能可以也可能不可以,这时的行为是由Sun和IBM的Preferences API实现决定的。(在相同的JDK实现上可以使用Preferences API来在不同的程序间共享数据) 一个Java软件需要让用户设置是否和操作系统一起启动,类似的需求还很多。这类需求就是要求Java程序有真正的和相关操作系统协同的能力。这种能力不是Preferences API的设计目标。 如果您对Preferences API还不了解,那么您可能需要阅读一下这篇文章用Preferences API存储对象,可以从参考资料中找到。 使用JNIWindows操作系统提供了操作注册表的API,因此用JNI将Java和这些API连接起来我们就获得了用Java操作注册表的能力。这说起来有些简单,实现起来却需要处理大量的细节。幸运的是这样的工作已经有人做了,我们要感谢他们。下面我们就来看看其中的一个包。com.ice.jni.registry包是通过JNI(Java native interface)实现的Windows注册表操作API,可以用来访问、修改和导出Windows注册表。现在这个包已经公开了,可以放心的使用而不必担心license的问题,并且包括一个构建好的DLL和Java、C的源代码。它可以在Java 1.1和更高的版本上工作。 如果您向我一样也对JNI感兴趣,那么这也是学习JNI的很好的示例。下面详细的描述一下这个包中的类,数量不是很多: HexNumberFormat 用来格式化和分析十六进制整数。 RegBinaryValue 表示类型为REG_BINARY的注册表值。REG_BINARY是指任意形式的二进制数。 RegDWordValue 表示类型为REG_DWORD的注册表值。REG_DWORD是指一个32位的整数。根据该整数的字节序不同又分为REG_DWORD_LITTLE_ENDIAN和REG_DWORD_BIG_ENDIAN。在Windows中REG_DWORD和REG_DWORD_LITTLE_ENDIAN有相同的含义。 RegistryValue 表示任意类型的注册表值,这是一个抽象类,不能被实例化。 RegMultiStringValue 表示类型为REG_MULTI_SZ的注册表值。REG_MULTI_SZ是一个null-terminated的字符串的序列。 RegStringValue 表示类型为REG_SZ和REG_EXPAND_SZ的注册表值。REG_SZ是指一个null-terminated的字符串,REG_EXPAND_SZ是指一个含有未展开的环境变量的null-terminated的字符串。 Registry 这个类定义了定级项(Key),包括HKEY_CLASSES_ROOT、HKEY_CURRENT_CONFIG、HKEY_CURRENT_USER、HKEY_DYN_DATA、HKEY_LOCAL_MACHINE、HKEY_PERFORMANCE_DATA和HKEY_USERS。还定义了错误代码,这些错误代码会包含在RegistryException中。最后是一些工具方法,如dumpHexData、exportRegistryKey、getErrorMessage、getTopLevelKey、openSubkey、parseArgumentString、parseArgumentVector、splitString和usage。 RegistryKey 定义了注册表的一个表项(Key)和相关的一些操作。 如果您需要了解更多的细节,请查阅参考资料中的JNIRegistry的Java doc、Registry和Registry Reference。 RegistryKey的方法概要:方法简短描述void closeKey()关闭该subkey。RegistryKey connectRegistry(java.lang.String hostName)连接远程主机hostName的注册表。RegistryKey createSubKey(java.lang.String subkey, java.lang.String className)创建和打开该key的subkey,具有写权限。RegistryKey createSubKey(java.lang.String subKey, java.lang.String className, int access)创建和打开该key的subkey,具有指定的权限。int decrDoubleWord(java.lang.String valueName)该方法将消减REG_DWORD的值。void deleteSubKey(java.lang.String subKey)删除该subkey。void deleteValue(java.lang.String valueName)删除一个命名的值。static java.lang.String expandEnvStrings(java.lang.String exString)展开exString中的环境变量。void export(java.io.PrintWriter out, boolean descend)导出key。void finalize()重载了的finalize()方法,确保能够关闭key。void flushKey()确保这个key被写到磁盘,对性能有一定的影响。java.lang.String getDefaultValue()得到该key的默认值。java.lang.String getFullName()得到key的全名。int getMaxSubkeyLength()得到所有subkey名称的最大长度。int getMaxValueDataLength()得到所有subkey值的最大长度。int getMaxValueNameLength()得到所有值的名称的最大长度。java.lang.String getName()得到该key的名称。int getNumberSubkeys()得到subkey的数量。int getNumberValues()得到值的数量。java.lang.String getStringValue(java.lang.String valueName)得到REG_SZ或REG_EXPAND_SZ的值。RegistryValue getValue(java.lang.String valueName)得到valueName的值。boolean hasDefaultValue()判断该key是否有默认值。boolean hasOnlyDefaultValue()判断该key是否只有默认值。int incrDoubleWord(java.lang.String valueName)该方法将增强REG_DWORD的值。java.util.Enumeration keyElements()枚举该key的subkey的名称。RegistryKey openSubKey(java.lang.String subkey)打开该key的subkey,具有读权限。RegistryKey openSubKey(java.lang.String subKey, int access)打开该key的subkey,具有指定的权限。java.lang.String regEnumKey(int index)得到该key在index处的subkey。java.lang.String regEnumValue(int index)得到该key在index处的subkey的值。void setCreated(boolean created)设置该key的created状态。void setValue(RegistryValue value)设置该key的值。void setValue(java.lang.String valueName, RegistryValue value)设置valueName的值。java.util.Enumeration valueElements() 枚举该key的值的名称。boolean wasCreated()判断该key是被opened还是被created和opened。最后我们来看一个代码示例:package org.solol.test;import com.ice.jni.registry.NoSuchKeyException;import com.ice.jni.registry.RegStringValue;import com.ice.jni.registry.Registry;import com.ice.jni.registry.RegistryException;import com.ice.jni.registry.RegistryKey;/* * author solo L * */public class JNIRegistryTest /* * param args */ public static void main(String args) /创建注册表项并设置相应的值 try RegistryKey software = Registry.HKEY_LOCAL_MACHINE .openSubKey(SOFTWARE); RegistryKey subKey = software.createSubKey(SubKeyName, ); subKey.setValue(new RegStringValue(subKey, subKey1, subKey1Value); subKey.setValue(new RegStringValue(subKey, subKey2, subKey2Value); subKey.closeKey(); catch (NoSuchKeyException e) e.printStackTrace(); catch (RegistryException e) e.printStackTrace(); /打开注册表项并读出相应的值 try RegistryKey software = Registry.HKEY_LOCAL_MACHINE. openSubKey(SOFTWARE); RegistryKey subKe
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025驾校考试宝典试题带答案
- 安徽省2022年普通高中学业水平合格性考试物理题目及答案
- 2025 年小升初承德市初一新生分班考试数学试卷(带答案解析)-(北师大版)
- 2025 年小升初保定市初一新生分班考试数学试卷(带答案解析)-(冀教版)
- 银行员工2025年终工作总结
- Python大模型基础与智能应用(微课版)-教学大纲、教案 黄恒秋
- 山东省东营市2024-2025学年高二下学期7月期末化学试题(含答案)
- 北师大版四年级上册数学第二单元 线与角 检测题(无答案)
- 单独小屋出租合同范本
- 农庄独院出租合同范本
- 陶行知教育名篇读书分享ppt
- 学前儿童数学教育高职全套完整教学课件
- 2022-2023年医疗招聘药学类-药剂学高频考点题库带答案
- 保洁常用清洁药剂培训课件
- ICU 危重患者CVC 及PICC 导管的留置选择及护理研究新进展
- 二年级四宫格六宫格数独练习
- 绿化考试试题及答案
- YY/T 0316-2008医疗器械风险管理对医疗器械的应用
- GB/T 18650-2008地理标志产品龙井茶
- 《工伤认定研究11000字【论文】》
- 医院进修生结业鉴定表
评论
0/150
提交评论