JNI --&-- JNA

别来无恙 提交于 2019-11-30 20:05:31

    最近写SDK,解释下什么是SDK,SDK一般是一些被软件工程师用于为特定的软件包、软件框架、硬件平台、操作系统等建立应用软件的开发工具的集合。开发SDK时使用JNI去调用SO或DLL是一件多么痛苦的事情啊,痛苦的让我有点想去学C的冲动。首先来解释下SO和DLL吧,SO和DLL是使用C语言来写的一个共享库。下面说说使用JNI和JNA的具体步骤吧:

    首先是让人灰常头痛的JNI:

        一:生成NativeJNIHelloWord.java文件

                public class NativeJNIHelloWord{

                            public native void displayHello();

                             static{

                                    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);
	}
	
}

 

 

            

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!