jnative的jar下载地址:
http://download.csdn.net/detail/heqinghua217/8865831
也可以去官网下载,地址如下
http://sourceforge.net/projects/jnative/
简单点的说明步骤:
我的是 windows环境 ,步骤如下,
1、把jnative.jar解压, 打开lib-bin目录,找到JNativeCpp.dll,把此文件放入系统盘,我的是c盘,路径如下, C:\Windows\System32 下
2、把自己要调用的动态库,放入你指定的目录,我这里放入的是F:\\EhfscliaxDll.dll
3、把jar导入到web项目的lib目录中,如果不是web项目,可以放入jdk的ext目录中,
4、执行如下代码:返回http://中文127.0.0.1:10087 表示成功
代码如下
public static void exeDll1(){
try {
System.load("F:\\EhfscliaxDll.dll");
JNative getUrl = new JNative("EhfscliaxDll.dll", "getUrl");
getUrl.setRetVal(Type.STRING);
getUrl.setParameter(0, "127.0.0.1");
getUrl.setParameter(1, 10087);
getUrl.setParameter(2, 123);
getUrl.invoke();
System.out.println(getUrl.getRetVal());
} catch (Exception e) {
e.printStackTrace();
}
}
--输出参数还是需要自己去定义的,比如我如下的列子,0-6是输入参数,7是输出参数,要获取输出参数,需要黑色字体的写法
原来是这么写的,设置返回值是getUrl.setRetVal(Type.String);获取返回值是:System.out.println(getUrl.getRetVal()); //,
然后输出了一大堆日志,报了一堆错误,改写成现在这样就好了,终于搞定了,
public static void exeDll2(){
try {
System.load("F:\\OnLineDll.dll");
JNative getUrl = new JNative("OnLineDll.dll", "OnlineSign");
getUrl.setRetVal(Type.INT);//返回状态
getUrl.setParameter(0, 1);
getUrl.setParameter(1, "1202020709914498651");
getUrl.setParameter(2, "20150714");
getUrl.setParameter(3, "1");
getUrl.setParameter(4, "1234567890");
getUrl.setParameter(5, "79274");
getUrl.setParameter(6, "false");
MemoryBlock m = MemoryBlockFactory.createMemoryBlock(1024);
//指向内存块的指针
Pointer pp = new Pointer(m);
getUrl.setParameter(7, pp); //输出参数
getUrl.invoke();
System.out.println(getUrl.getRetVal());//调用状态
System.out.println(pp.getAsString());//输出参数
// 原来是这么写的,设置返回值是getUrl.setRetVal(Type.String);获取返回值是:System.out.println(getUrl.getRetVal()); //,然后输出了一大堆日志,报了一堆错误,改写成现在这样就好了,终于搞定了
getUrl.dispose(); // 记得释放
} catch (Exception e) {
e.printStackTrace();
}
}
------------------------------ 以下内容来自 http://tvjody.iteye.com/blog/125643 (他写的很好)
因为项目的需求,要在JAVA项目中调用Windows的Dll(动态链接库)文件,之前用Jni调用过C写的Dll文件,比较麻烦,这里不多说,网上也有很多这方面的文档。
在网上找到一个开源的组件JNative,使用后感觉比较方便。
-
获得三个文件,分别是:JNativeCpp.dll,libJNativeCpp.so,JNative.jar 。
JNativeCpp.dll Windows下用的,拷贝到windows / system32目录下;
libJNativeCpp.so Linux下的,拷贝到系统目录下;
JNative.jar 这是一个扩展包,导入工程LIB中或将其拷贝到jdk\jre\lib\ext 下,系统会自动加载。 -
使用说明
我的项目将使用JNative组件调用一个测试应用服务器状态的TestAppSvr.dll文件,Dll文件中包含一个TestConnect()方法,返回一个整形的结果(1或0)
首先配置好JNative组件的windows环境:
将Native要用到JNativeCpp.dll放在系统盘的\WINDOWS\system32下
将JNative.jar导入工程中,新建一个调用类:java 代码- package com.tvjody;
- import java.io.File;
- import java.io.FileOutputStream;
- import java.io.IOException;
- import java.io.InputStream;
- import org.xvolks.jnative.JNative;
- import org.xvolks.jnative.Type;
- import org.xvolks.jnative.exceptions.NativeException;
- public class AppSvrTestConnect {
- public AppSvrTestConnect() {
- }
- /**
- * 测试应用服务器连接状态
- *
- * TestConnect
- * @param ip 应用服务器IP
- * @param port 端口
- * @param intrcpt 是否采用数据压缩方式 1 :true 0:false
- * @return int 1 :成功 0:失败
- * @throws NativeException
- * @throws IllegalAccessException
- */
- private static final int TestConnect(String ip, int port, int intrcpt)throws NativeException, IllegalAccessException {
- JNative n = null;
- try {
- n = new JNative("TestAppSvr.dll", "TestConnect");
- n.setRetVal(Type.INT);
- int i = 0;
- n.setParameter(i++, Type.STRING, ip);
- n.setParameter(i++, Type.INT, "" + port);
- n.setParameter(i++, Type.INT, "" + intrcpt);
- n.invoke();
- return Integer.parseInt(n.getRetVal());
- } finally {
- if (n != null)
- n.dispose();
- }
- }
- /**
- * 指定Dll文件路径,动态加载本地链接库,测试应用服务器连接状态
- * setDllPath
- * @param path Dll文件的路径,不包含DLL名称 例如:windows - d:\test\test\ unix - root/test/test/
- * @param ip 应用服务器IP
- * @param port 端口
- * @param intrcpt 是否采用数据压缩方式 1 :true 0:false
- * @return int 1 :成功 0:失败
- * @throws NativeException
- * @throws IllegalAccessException
- */
- public static final int TestConnectFromDllPath(String path,String ip, int port, int intrcpt) throws NativeException, IllegalAccessException{
- path += "TestAppSvr.dll";
- System.load(path);
- return TestConnect(ip,port,intrcpt);
- }
- /**
- * Dll文件放在JRE\bin目录下面,ClassLoader就能通过System.loadLibrary()动态加载本地链接库
- * TestConnectFromDllPath
- * @param ip 应用服务器IP
- * @param port 端口
- * @param intrcpt 是否采用数据压缩方式 1 :true 0:false
- * @return int 1 :成功 0:失败
- * @throws NativeException
- * @throws IllegalAccessException
- */
- public static final int TestConnectFromDllPath(String ip, int port, int intrcpt) throws NativeException, IllegalAccessException{
- System.loadLibrary("TestAppSvr");
- return TestConnect(ip,port,intrcpt);
- }
- }
这个类实现了一个静态私有方法,用来调用Dll文件中的方法返回结果
private static final int TestConnect(String ip, int port, int intrcpt)
两个静态公共方法,分两种方式装载DLL文件
public static final int TestConnectFromDllPath(String path,String ip, int port, int intrcpt) //通过DLL文件的路径
public static final int TestConnectFromDllPath(String ip, int port, int intrcpt) //通过ClassLoader
然后新建一个类,调用AppSvrTestConnect.java,实现方法一调用,我是将TestAppSvr.dll文件与Demo.java放在一个目录下 ,所以得到Demo.java的路径后就可以得到TestAppSvr.dll的路径,调用AppSvrTestConnect.TestConnectFromDllPath()方法后就能返回正确的信息.方法二是已经将TestAppSvr.dll放在了Jre\bin目录下,在JVM的Classloader的时候会自动加载,然后通过System.loadLibrary("TestAppSvr")就可以装配DLL文件.
- public class Demo {
- public int getInfo() throws NativeException, IllegalAccessException{
- String path=getClass().getResource(File.separator).getPath();
- path = path.substring(1,path.length());
- System.out.println(path); //得到DLL文件的路径
- String ip = "192.168.0.48"; //服务器IP
- int port = 221; //端口
- int intrcpt = 1; //数据压缩方式传送,1为采用;0为不采用
- //方法1 传入Dll文件的路径
- //int info = AppSvrTestConnect.TestConnectFromDllPath(path, ip, port, intrcpt);
- //方法2 Dll文件已经放在JRE\bin目录下面
- int info = AppSvrTestConnect.TestConnectFromDllPath(ip, port, intrcpt);
- //1为成功,0为失败
- if (info == 1)
- System.out.println("应用服务器可用。");
- else
- System.out.println("应用服务器不可用,请检查IP地址和端口是否正确。");
- return info;
- }
System.loadLibrary():装载Windows\System32下或jre\bin或Tomcat\bin目录下的本地链接库
System.load():根据具体的目录来加截本地链接库,必须是绝对路径
-
备注
上面的示例工程,因为是例子,所以没有大多的设计,只是实现了装载DLL文件,调用DLL文件方法,返回信息.
JNative的详细说明,请参考JNative的源程序和例子.
注意JVM只允许一个默认的ClassLoader来load native library,同时并不提供专门的API来unload一个loaded native library,所以在项目调试的时候,独立启动Web Server.
---------------------------------注意事项:来自http://www.cnblogs.com/beastplus/p/3156080.html
JNative用法注意事项
公司要做个跟设备打交道的web系统,需要java调用dll。搞java的同事说JNative看起来挺好使的,找俺帮忙调通。用的是1.3.1版本
- 环境设置。
JNative的调试信息需要打开才能更清楚些,要不总是说没加载库,跟没说一样。
System.setProperty("jnative.debug", "true");
如果调试信息里有System.LoadLibrary(),说明没有加载JNativeCpp.dll,指定全路径即可,双斜杠哦。
System.setProperty("jnative.loadNative", "D:\\Test\\JNativeCpp.dll");
- lib库路径问题
- windows
在windows下需要把调用的dll路径设置到环境变量PATH中,除非你不介意拷到win32中,dll依赖的库也得在PATH或win32中。
- linux
linux下同样需要设置环境变量,编辑bashrc,添加 export LD_LIBRARY=so路径,依赖的库也得在PATH中,除非都放在/usr/lib/下
- windows
- lib库名称问题
无论linux还是windows在JNative的构造函数中的lib库名字为库全名,包括扩展名dll、so,而且so需要包括前面的‘lib’,貌似与网上说的不太一样。
- 资源释放问题
有些设备需要先初始化在操作,最后释放,所有功能都分散在不同函数中,JNative需要有个静态的实例,每次创建调用函数时lib库依旧是加载的。
-----------------------------------------------------------一下文章来自http://blog.163.com/wex660@126/blog/static/24153065201031554358152/
今天,使用JNative遇到了一些小问题,郁闷是我,弄了很久才发现问题的所在:
先说一下JNative的使用吧(JNative是封装了访问动态库的相关东西,方便java访问动态库的一个jar包):
首先:下载JNative(http://sourceforge.net/projects/jnative/)又是sourceforge的东西;
其次:将你需要调用的的动态库放到系统系统盘下的system32或者其他地方(这些其他地方你可以查一下,WEB 项目则将动态库拷贝到容器的bin目录下,如tomcat的bin下 );
再次: 建立一个java项目,在项目中调用动态库,我这里粘贴一个我的例子供参考:
package com.gxmis.password;
imp
imp
imp
imp
imp
imp
imp
//这是CAS里要使用的一个加密类,我实现了PasswordEncoder 的接口
public class AccPasswordEncoder implements PasswordEncoder {
public AccPasswordEncoder(){
}
//重写的加密方法
public String encode(String pass) {
//定义JNative
JNative jn = null;
//返回密码的长度
int retInt ;
//返回的密码字符串
String retPass = "";
try {
//申请一个内存块,因为要将加密后的数据取回来用,所以将加密后的数据放在这个内存块,方便返回的时候取出
MemoryBlock m = MemoryBlockFactory.createMemoryBlock(1024);
//指向内存块的指针
Pointer pp = new Pointer(m);
//设置日志记录的开启,方便跟踪JNative的运行过程
JNative.setLoggingEnabled(true);
//加载系统system32目录下的动态库
System.loadLibrary("encrypt");
//将动态库的名字和方法传递给JNative
jn= new JNative ("encrypt","encrypttext");
//设置调用动态库的方法后的返回类型(即encrypttext方法的返回类型)
jn.setRetVal(Type.INT);
int passLen = pass.length();
int intOut = 2 * passLen + 16;
//注意,我的encrypttext方法是有4个参数的,返回值为整型,第0,2个参数是字符串,第1,3个是整形
jn.setParameter(0, pass);
jn.setParameter(1, passLen);
jn.setParameter(2, pp);
jn.setParameter(3, intOut);
//调用encrypttext方法
jn.invoke();
//获得返回值
intOut = Integer.parseInt(jn.getRetVal());
if (intOut == -1){
jn.dispose();
retPass = "";
}
else{
jn.dispose();
//取得加密数据
retPass = pp.getAsString().substring(0,6);
}
} catch (NativeException e) {
System.out.println("NativeException异常:");
e.printStackTrace();
} catch (IllegalAccessException e) {
System.out.println("IllegalAccessException异常:");
e.printStackTrace();
}finally{
try {
jn.dispose();
} catch (NativeException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
return retPass;
}
}
我自己是调用动态库进行加密的操作:
遇到的问题1:
这个问题是找不到日志文件的异常,但是加密已经完成,从数据可以看出来:
2009-11-5 10:43:01, [DEBUG] [org.xvolks.jnative.JNative] [loadLibrary]: Successfully loaded library 'encrypt', functionName = encrypttext: hModule = 268435456
1af154(这个是加密后出现的数据)java.lang.NoSuchFieldError: lastError
at org.xvolks.jnative.JNative.nInvoke(Native Method)
at org.xvolks.jnative.JNative.invoke(JNative.java:807)
at com.passkey.AccPasswordEncoder.encode(AccPasswordEncoder.java:50)
at com.passkey.test.main(test.java:10)
2009-11-5 10:43:01, [DEBUG] [org.xvolks.jnative.JNative] [unLoad]: Unloading native library 'encrypt'
ccx_jni_utils.c.writeLog : can't get a Java Logger instance.
Exception in thread "main"
解决办法:这个问题是jar包的原因,更新新版本的JNative.jar包就可以解决
遇到的问题2:
JVM的问题:
#
# An unexpected error has been detected by Java Runtime Environment:
#
# EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x02e37b1a, pid=4008, tid=456
#
# Java VM: Java HotSpot(TM) Client VM (1.6.0-beta2-b86 mixed mode, sharing)
# Problematic frame:
# C [IC_WS_CPU.dll+0x7b1a]
#
# If you would like to submit a bug report, please visit:
# http://java.sun.com/webapps/bugreport/crash.jsp
#
解决办法:是JDK版本的原因,注意要更新JDK的版本,1.5以下的可能会出现一些异常,更新到1.6的正式发布版本(尽量不使用测试版本)就好了
遇到的问题3:
我看网上还有个问题是:
开发一个web的时候,一个类用了JNative,JNativeCpp.dll文件发到了windows/system32下面,
junit 也测试通过了,实际调用的时候报了个
java.lang.IllegalStateException: JNative library not loaded, sorry !
at org.xvolks.jnative.JNative. <init>(JNative.java:337)
at org.xvolks.jnative.JNative. <init>(JNative.java:269)
....
的错误,
后来把JNativeCpp.dll拷到tomcat的bin下面就解决了。
不过,不知道了解里面的机制。
我也试了一下不用将JNativeCpp.dll拷贝到相应的目录,因为最新的JNative.jar包里面是打包了JNativeCpp.dll文件,所以这个问题在新版本我是没有遇到
以上的是鄙人遇到的一些东西,记录下来方便查找,若有错误之处忘回帖指教,若你也遇到了问题,也麻烦你写下问题和问题的解决办法,大家共同学习进步,谢谢.