最近写SDK,解释下什么是SDK,SDK通常是一些被软件工程师用于为特定的软件包、软件框架、硬件平台、操做系统等创建应用软件的开发工具的集合。开发SDK时使用JNI去调用SO或DLL是一件多么痛苦的事情啊,痛苦的让我有点想去学C的冲动。首先来解释下SO和DLL吧,SO和DLL是使用C语言来写的一个共享库。下面说说使用JNI和JNA的具体步骤吧: java
首先是让人灰常头痛的JNI: 程序员
一:生成NativeJNIHelloWord.java文件 windows
public class NativeJNIHelloWord{ 框架
public native void displayHello(); jvm
static{ socket
System.out.println("hello"); 工具
} 开发工具
static{ 操作系统
System.load("xx.so"); 日志
/*
加载so或dll,System.load2.System.load 参数为库文件的绝对路径,能够是任意路径。
例如你能够这样载入一个windows平台下JNI库文件:
System.load("C:\\Documents and Settings\\TestJNI.dll");。
3. System.loadLibrary 参数为库文件名,不包含库文件的扩展名。
例如你能够这样载入一个windows平台下JNI库文件
System. loadLibrary ("TestJNI");
这里,TestJNI.dll 必须是在java.library.path这一jvm变量所指向的路径中。
能够经过以下方法来得到该变量的值:
System.getProperty("java.library.path");
默认状况下,在Windows平台下,该值包含以下位置:
1)和jre相关的一些目录
2)程序当前目录
3)Windows目录
4)系统目录(system32)
5)系统环境变量path指定目录
*/
}
}
二:javac命令将.java文件生成.class文件
三:javah命令将.class文件生成.h头文件 该文件供给C进行调用
java程序员到这里就能够了,剩下的是C程序员给你so或dll文件便可。
JNA解决JNI的缺点:
JNA的开发步骤:
第一步:下载JNA的jar包,能够去com.sun的官网上去下jna-3.0.1.jar
第二步:编写JNA的类,其内部定义接口,使接口实现library接口。
接口内部的方法须要和dll或so内定义的相一致,其中须要注意的是C中的char* 对应java中的String
C中的wchar_t* 对应java的WString,JNA提供一个INSTANCE属性,经过该属性进行调用类中的方法。
public class JNAHelloWord{
public instance Ioftp extends Library{
public void display();
public int FtpRev(WString rfile,int id,String ms);
}
public static Ioftp Instance=(Ioftp)Native.loadLibrary("ftpdll",Ioftp.class);//注意只须要SO或dll的文件名,不须要带后缀
}
如下是真实的java代码:
package com.icms.sdk.oftpd; public interface IOFTPD { // 打开链接 host:ip地址 port:端口号 public int FTPopen(String host, int port); // 关闭链接 public int FTPclose(); // 发送数据 lfile:本地文件名 rfile:远程文件名 msSysCode:系统标识 public int FTPsend(String lfile, String rfile, String msSysCode); // 接受数据 rfile,远程文件名 lfile,本地文件名 msSysCode:系统标识 public int FTPrecv(String rfile, String lfile, String msSysCode); // 设置参数(超时时间的设置 id可能有十几种类型) public int FTPsetflag(int id, int flag); // 删除文件夹 dir:目录 msSysCode:系统标识 public int FTPrmdir(String dir, String msSysCode); // 查询文件夹下全部文件列表 dir:目录 msSysCode:系统标识 public String FTPlistForJava(String rPath, String msSysCode); }
package com.icms.sdk.oftpd; import java.io.BufferedOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.FileWriter; import java.io.IOException; import java.io.InputStream; import com.icms.sdk.util.PropertiesUtil; import com.sun.jna.Library; import com.sun.jna.Native; import com.sun.jna.WString; /** * 文件传输 * <p> * <br> * <b>Package_name:</b>boc.oftpd<br> * <b>Class_name:</b>FileTransfer.java<br> * <b>Company:</b>Founder<br> * <b>Date:</b>Nov 7, 2012 - 10:42:32 AM<br> * * @author xg * </p> */ public class JNAFileTransfer implements IOFTPD { private static final boolean isWindows = System.getProperty("os.name").toLowerCase().indexOf("windows") != -1; private static IOftpd INSTANCE = loadDll(); /** * 工具类判断操做系统,动态载入dll或so文件 */ public static IOftpd loadDll() { IOftpd oftpd = null; String DLL_FUNCNAME = PropertiesUtil.getProperty("DLL_FUNCNAME"); if (DLL_FUNCNAME == null) { DLL_FUNCNAME = "ftpdll"; } String DLL_FILENAME = isWindows ? DLL_FUNCNAME + ".dll" : DLL_FUNCNAME + ".so"; File dllFile = new File(new File(System.getProperty("user.dir")), DLL_FILENAME); if (!dllFile.exists()) { fileCopy(DLL_FILENAME); if (isWindows) { fileCopy("msvcr100.dll"); } } System.load(dllFile.getAbsolutePath()); oftpd = (IOftpd) Native.loadLibrary(DLL_FUNCNAME, IOftpd.class); return oftpd; } /** * 拷贝文件至{user.dir}目录下 * * @param filePath */ private static void fileCopy(String DLL_FILENAME) { InputStream in = null; BufferedOutputStream out = null; File dllFile = new File(new File(System.getProperty("user.dir")), DLL_FILENAME); try { in = JNAFileTransfer.class.getResourceAsStream("/" + DLL_FILENAME); byte[] buffer = new byte[512]; out = new BufferedOutputStream(new FileOutputStream(dllFile)); while (true) { int readed = in.read(buffer); if (readed <= -1) break; out.write(buffer, 0, readed); } } catch (Exception e) { } finally { if (out != null) { try { out.close(); } catch (Exception e) { } } if (in != null) { try { in.close(); } catch (Exception e) { } } dllFile = null; } } public interface IOftpd extends Library { // 打开链接 host:ip地址 port:端口号 public int FTPopen(String host, int port); // 关闭链接 public int FTPclose(); // 发送数据 lfile:本地文件名 rfile:远程文件名 msSysCode:系统标识 public int FTPsend(WString lfile, WString rfile, String msSysCode); // 接受数据 rfile,远程文件名 lfile,本地文件名 msSysCode:系统标识 public int FTPrecv(WString rfile, WString lfile, String msSysCode); // 设置参数(超时时间的设置 id可能有十几种类型) public int FTPsetflag(int id, int flag); // 删除文件夹 dir:目录 msSysCode:系统标识 public int FTPrmdir(WString dir, String msSysCode); // 查询文件夹下全部文件列表 dir:目录 msSysCode:系统标识 public WString FTPlistForJava(WString rPath, String msSysCode); } private synchronized static boolean write(String path, String content) { FileWriter fw = null; try { fw = new FileWriter(path, true); fw.write(content + "\r\n"); fw.flush(); } catch (IOException e) { } finally { try { fw.close(); } catch (IOException e) { } } return true; } public int FTPclose() { return INSTANCE.FTPclose(); } public String FTPlistForJava(String path, String msSysCode) { String temp=""; WString list=INSTANCE.FTPlistForJava(new WString(path), msSysCode); if(list!=null){ temp=list.toString(); } return temp; } public int FTPopen(String host, int port) { return INSTANCE.FTPopen(host, port); } public int FTPrecv(String rfile, String lfile, String msSysCode) { FTPsetflag(); return INSTANCE.FTPrecv(new WString(rfile), new WString(lfile),msSysCode); } public int FTPrmdir(String dir, String msSysCode) { return INSTANCE.FTPrmdir(new WString(dir), msSysCode); } public int FTPsend(String lfile, String rfile, String msSysCode) { FTPsetflag(); return INSTANCE.FTPsend(new WString(lfile), new WString(rfile),msSysCode); } public int FTPsetflag(int id, int flag) { return INSTANCE.FTPsetflag(id, flag); } /** * 设置文件传输的发送和接收超时时间 */ private void FTPsetflag() { /** 设置log日志默认不启用 **/ String FTPLogSwitch = PropertiesUtil.getProperty("FTPLogSwitch"); if (!FTPConstant.FTPLogSetFlag.ISFTPDEBUG.equals(FTPLogSwitch)) { FTPsetflag(FTPConstant.FTPLogSetFlag.ID, FTPConstant.FTPLogSetFlag.OFF_FLAG); } else { FTPsetflag(FTPConstant.FTPLogSetFlag.ID, FTPConstant.FTPLogSetFlag.ON_FLAG); } // 设置文件发送传输超时时间 int ftpSendTimeout = FTPConstant.FTPSendTimeoutSetFlag.DEFAULT_FLAG; String FTPsendTimeout = PropertiesUtil.getProperty("sendTimeout"); if (!"".equals(FTPsendTimeout) && null != FTPsendTimeout && ftpSendTimeout < Integer.parseInt(FTPsendTimeout)) { ftpSendTimeout = Integer.parseInt(FTPsendTimeout); } FTPsetflag(FTPConstant.FTPSendTimeoutSetFlag.ID, ftpSendTimeout); int ftpRecvTimeout = FTPConstant.FTPRecvTimeoutSetFlag.DEFAULT_FLAG; String recvTimeout = PropertiesUtil.getProperty("recvTimeout"); if (!"".equals(recvTimeout) && null != recvTimeout && ftpRecvTimeout < Integer.parseInt(recvTimeout)) { ftpRecvTimeout = Integer.parseInt(recvTimeout); } FTPsetflag(FTPConstant.FTPRecvTimeoutSetFlag.ID, ftpRecvTimeout); } public static void main(String[] args) { // 1. 新建一个1.txt文件 File tempFile = new File(new File(System.getProperty("user.dir")),"1.txt"); String tempFilePath = tempFile.getAbsolutePath(); write(tempFilePath, "11111111111111111111111111111111111111111111111"); // 2. 得到实例 JNAFileTransfer obj = new JNAFileTransfer(); // 3. 打开连接 obj.FTPopen("192.168.1.244", 10000); // 4.上传1.txt文件 obj.FTPsend(tempFilePath, "1.txt", "01"); // 5. 删除本地文件 tempFile.delete(); // 6. 下载1.txt文件 obj.FTPrecv("1.txt", tempFilePath, "01"); // 6. list System.out.println(obj.FTPlistForJava("sdk", "01")); //7. 删除远程文件夹 obj.FTPrmdir("sdk/ftplog", "01"); // 8. 删除临时文件 File temp = new File(tempFilePath); System.out.println(temp.exists()); temp.delete(); // 7. 关闭连接 obj.FTPclose(); } }package com.icms.sdk.oftpd; import java.io.BufferedOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.FileWriter; import java.io.IOException; import java.io.InputStream; import com.icms.sdk.util.PropertiesUtil; /** * 文件传输海外版本JNI实现,目前仅支持AIX操做系统 * <p> * <br> * <b>Package_name:</b>com.icms.sdk.oftpd<br> * <b>Class_name:</b>JNIFileTransfer.java<br> * <b>Company:</b>Founder<br> * <b>Date:</b>Nov 7, 2012 - 10:42:32 AM<br> * * @author xg * </p> */ public class JNIFileTransfer implements IOFTPD { private static IOftpd INSTANCE = loadDll(); /** * 工具类判断操做系统,动态载入dll或so文件 */ public static IOftpd loadDll() { IOftpd oftpd = null; String DLL_FUNCNAME = PropertiesUtil.getProperty("DLL_FUNCNAME"); String DLL_FILENAME = DLL_FUNCNAME+ ".so"; File dllFile = new File(new File(System.getProperty("user.dir")),DLL_FILENAME); if (!dllFile.exists()) { fileCopy(DLL_FILENAME); } System.load(dllFile.getAbsolutePath()); return oftpd; } /** * 拷贝文件至{user.dir}目录下 * * @param filePath */ private static void fileCopy(String DLL_FILENAME) { InputStream in = null; BufferedOutputStream out = null; File dllFile = new File(new File(System.getProperty("user.dir")), DLL_FILENAME); try { in = JNIFileTransfer.class.getResourceAsStream("/" + DLL_FILENAME); byte[] buffer = new byte[512]; out = new BufferedOutputStream(new FileOutputStream(dllFile)); while (true) { int readed = in.read(buffer); if (readed <= -1) break; out.write(buffer, 0, readed); } } catch (Exception e) { } finally { if (out != null) { try { out.close(); } catch (Exception e) { } } if (in != null) { try { in.close(); } catch (Exception e) { } } dllFile = null; } } public class IOftpd { //打开链接 host:ip地址 port:端口号 public native int FTPopen(String host, int port); //关闭链接 public native int FTPclose(); //发送数据 lfile:本地文件名 rfile:远程文件名 msSysCode:系统标识 public native int FTPsend(String lfile, String rfile, String msSysCode); //接受数据 rfile:远程文件名 lfile:本地文件名 msSysCode:系统标识 public native int FTPrecv(String rfile, String lfile, String msSysCode); //设置参数(超时时间的设置 id可能有十几种类型) public native int FTPsetflag(int id, int flag); //删除文件夹 dir:目录 msSysCode:系统标识 public native int FTPrmdir(String dir, String msSysCode); //查询文件夹下全部文件列表 dir:目录 msSysCode:系统标识 public native String FTPlist(String dir, String msSysCode); } private synchronized static boolean write(String path, String content) { FileWriter fw = null; try { fw = new FileWriter(path, true); fw.write(content + "\r\n"); fw.flush(); } catch (IOException e) { } finally { try { fw.close(); } catch (IOException e) { } } return true; } public int FTPclose() { return INSTANCE.FTPclose(); } public String FTPlistForJava(String path, String msSysCode) { return INSTANCE.FTPlist(path, msSysCode); } public int FTPopen(String host, int port) { return INSTANCE.FTPopen(host, port); } public int FTPrecv(String rfile, String lfile, String msSysCode) { FTPsetflag(); return INSTANCE.FTPrecv(rfile, lfile,msSysCode); } public int FTPrmdir(String dir, String msSysCode) { return INSTANCE.FTPrmdir(dir, msSysCode); } public int FTPsend(String lfile, String rfile, String msSysCode) { FTPsetflag(); return INSTANCE.FTPsend(lfile, rfile,msSysCode); } public int FTPsetflag(int id, int flag) { return INSTANCE.FTPsetflag(id, flag); } /** * 设置文件传输的发送和接收超时时间 */ private void FTPsetflag() { /** 设置log日志默认不启用 **/ String FTPLogSwitch = PropertiesUtil.getProperty("FTPLogSwitch"); if (!FTPConstant.FTPLogSetFlag.ISFTPDEBUG.equals(FTPLogSwitch)) { FTPsetflag(FTPConstant.FTPLogSetFlag.ID, FTPConstant.FTPLogSetFlag.OFF_FLAG); } else { FTPsetflag(FTPConstant.FTPLogSetFlag.ID, FTPConstant.FTPLogSetFlag.ON_FLAG); } // 设置文件发送传输超时时间 int ftpSendTimeout = FTPConstant.FTPSendTimeoutSetFlag.DEFAULT_FLAG; String FTPsendTimeout = PropertiesUtil.getProperty("sendTimeout"); if (!"".equals(FTPsendTimeout) && null != FTPsendTimeout && ftpSendTimeout < Integer.parseInt(FTPsendTimeout)) { ftpSendTimeout = Integer.parseInt(FTPsendTimeout); } FTPsetflag(FTPConstant.FTPSendTimeoutSetFlag.ID, ftpSendTimeout); int ftpRecvTimeout = FTPConstant.FTPRecvTimeoutSetFlag.DEFAULT_FLAG; String recvTimeout = PropertiesUtil.getProperty("recvTimeout"); if (!"".equals(recvTimeout) && null != recvTimeout && ftpRecvTimeout < Integer.parseInt(recvTimeout)) { ftpRecvTimeout = Integer.parseInt(recvTimeout); } FTPsetflag(FTPConstant.FTPRecvTimeoutSetFlag.ID, ftpRecvTimeout); } public static void main(String[] args) { // 1. 新建一个1.txt文件 File tempFile = new File(new File(System.getProperty("user.dir")),"1.txt"); String tempFilePath = tempFile.getAbsolutePath(); write(tempFilePath, "11111111111111111111111111111111111111111111111"); // 2. 得到实例 JNIFileTransfer obj = new JNIFileTransfer(); // 3. 打开连接 obj.FTPopen("192.168.1.244", 10000); // 4.上传1.txt文件 obj.FTPsend(tempFilePath, "1.txt", "01"); // 5. 删除本地文件 tempFile.delete(); // 6. 下载1.txt文件 obj.FTPrecv("1.txt", tempFilePath, "01"); // 6. list System.out.println(obj.FTPlistForJava("sdk", "01")); obj.FTPrmdir("sdk/ftplog", "01"); // 8. 删除临时文件 File temp = new File(tempFilePath); System.out.println(temp.exists()); temp.delete(); // 7. 关闭连接 obj.FTPclose(); } }
package com.icms.sdk.oftpd; import java.io.File; import com.icms.sdk.util.FTPUtil; import com.icms.sdk.util.PropertiesUtil; import com.icms.sdk.util.UserDFException; /** * 文件传输对外仅暴露这个工具类型 * @author Administrator * */ public class OftpdUtil { /** * 获取socket操做时间 * getSocketOpTime * @return * @author huangyi */ public static int getSocketOpTime(){ int otTimeout = FTPUtil.DEFAULT_OT_TIMEOUT; String socketTimeout = PropertiesUtil.getProperty("OT_TIMEOUT"); if (!"".equals(socketTimeout) && null != socketTimeout) { otTimeout = Integer.parseInt(socketTimeout); } return otTimeout; } public void uploadFile(String ip, int port, String localFile, String ftpFile, String systemId) throws UserDFException { FileTransfer tran=new FileTransfer(); // 打开端口 int rtnflag = tran.FTPopen(ip, port); if(rtnflag!=0){ throw new UserDFException("FTPopen Exception, rtnflag="+rtnflag); } // 上传文件 localPath ftpPath if(tran.FTPsend(localFile, ftpFile, systemId)!=0){ throw new UserDFException("FTPsend Exception, rtnflag="+rtnflag); } // 关闭端口 if(rtnflag==0){ tran.FTPclose(); } } /** *多文件上传 * @param ip * @param port * @param localPath * @param ftpPath * @param systemId * @throws UserDFException */ public void uploadFiles(String ip, int port, String localPath, String ftpPath, String systemId) throws UserDFException { // 打开端口 FileTransfer tran=new FileTransfer(); int rtnflag = tran.FTPopen(ip, port); if(rtnflag!=0){ throw new UserDFException("FTPopen Exception, rtnflag="+rtnflag); } File file = new File(localPath); if (!file.exists()) { throw new UserDFException("localPath not exists, FilePath="+localPath); } // 上传文件 localPath ftpPath String[] sb = file.list(); for(int i=0;i<sb.length;i++){ if(tran.FTPsend(localPath+"/"+sb[i], ftpPath+"/"+sb[i], systemId)!=0){ throw new UserDFException("FTPsend Exception, rtnflag="+rtnflag); } } // 关闭端口 if(rtnflag==0){ tran.FTPclose(); } } /** * 多文件下载 * downloadFile * @param ftpPath * @param localPath * @param systemId * @author huangyi * @throws UserDFException */ public void downloadFile(String ip, int port, String ftpPath, String localPath, String systemId) throws UserDFException { FileTransfer tran=new FileTransfer(); boolean flag = true; int rtnflag = -1; // 打开端口 rtnflag = tran.FTPopen(ip, port); if(rtnflag!=0){ throw new UserDFException("FTPopen Exception, rtnflag="+rtnflag); } // 循环下载文件 String File = tran.FTPlistForJava(ftpPath, systemId); String[] fileList = File.split("\\|"); for(int i=0;i<fileList.length;i++){ if(tran.FTPrecv(ftpPath+"/"+fileList[i], localPath+"/"+fileList[i], systemId)!=0){ flag=false; throw new UserDFException("FTPrecv Exception, rtnflag="+rtnflag); } } // 删除ftp目录文件 if(flag){ tran.FTPrmdir(ftpPath, systemId); } // 关闭端口 if(rtnflag==0){ tran.FTPclose(); } } }
package com.icms.sdk.oftpd; public class FileTransfer implements IOFTPD { private IOFTPD oftpd=getInstance(); private static final boolean isAIX = System.getProperty("os.name").toLowerCase().indexOf("aix") != -1; private IOFTPD getInstance() { IOFTPD oftpd=null; if(isAIX){ oftpd=new JNIFileTransfer(); }else{ oftpd=new JNAFileTransfer(); } return oftpd; } public int FTPclose() { return 0; } public String FTPlistForJava(String path, String msSysCode) { return oftpd.FTPlistForJava(path, msSysCode); } public int FTPopen(String host, int port) { return oftpd.FTPopen(host, port); } public int FTPrecv(String rfile, String lfile, String msSysCode) { return oftpd.FTPrecv(rfile, lfile, msSysCode); } public int FTPrmdir(String dir, String msSysCode) { return oftpd.FTPrmdir(dir, msSysCode); } public int FTPsend(String lfile, String rfile, String msSysCode) { return oftpd.FTPsend(lfile, rfile, msSysCode); } public int FTPsetflag(int id, int flag) { return oftpd.FTPsetflag(id, flag); } }