java jni实现linux环境下绑定硬件的License
由于系统运行在Linux环境中,该License绑定服务器的cpuid和mac等信息,而java实现起来不太方便所以就利用了JNI
问题及解决方法:
1、System.loadLibrary("License");时出错
解决:libLicense.so文件要放到正确的目录下,可以利用System.getProperty("java.library.path"));打印出path,我放的是 /lib/ 下面
2、verifylicense 本地方法找不到
解决:头文件和C的JNIEXPORT 定义的方法名要正确,包含License.java的包名,如果Java中定义的method有划线的话,头文件中下划线后面要紧跟一个1
3、加载文件和方法都没有问题,运行的时候没有执行
解决:这个问题困扰了我一段时间,最后发现安装环境时加了一个文件:/etc/profile,而这个文件里面没有声明CATALINA_HOME、CATALINA_BASE,并且CLASSPATH里面没有带上servlet-api.jar包,所以native方法无法在servlet容器中执行
部分代码:
1、web.xml
<servlet><servlet-name>license</servlet-name><servlet-class>com.blingtel.common.util.License</servlet-class><load-on-startup>1</load-on-startup></servlet>
package com.xxx.common.util;import javax.servlet.ServletConfig;import javax.servlet.ServletException;import javax.servlet.http.HttpServlet;import org.apache.commons.logging.Log;import org.apache.commons.logging.LogFactory;/* * 文件名称: CheckLicense.java * 文件描述: <描述> * @version 1.0 * @author *//** * <校验License> * <功能详细描述> * @author zengyouyuan * @version [版本号, 2013-7-5] * @see [相关类/方法] * @since [产品/模块版本] */public class License extends HttpServlet{ /** * 注释内容 */ private static final long serialVersionUID = 1L; /** * 日志对象 */ private static Log logger = LogFactory.getLog(License.class); private native boolean verifylicense(); static { int i = 0; try { logger.error("loadLibary start..."); System.loadLibrary("License"); i = 1; logger.error("load Libary OK..."); } catch (Exception e) { i = 2; // TODO Auto-generated catch block logger.error("load error"); e.printStackTrace(); Runtime runtime = Runtime.getRuntime(); try { i = 3; logger.error("load libLicense.so error, killall java"); runtime.exec("killall java"); } catch (Exception e1) { i = 4; // TODO Auto-generated catch block e1.printStackTrace(); } } finally { logger.error("i = " + i); if (i == 0) { Runtime runtime = Runtime.getRuntime(); try { logger.error("load libLicense.so error, killall java"); runtime.exec("killall java"); System.exit(0); } catch (Exception e1) { // TODO Auto-generated catch block e1.printStackTrace(); } } } } public void init(ServletConfig servletConfig) throws ServletException { logger.error("income License.init()"); License l = new License(); if (l.verifylicense()) { logger.error("verify_license ERROR"); Runtime runtime = Runtime.getRuntime(); try { logger.error("verify license failed, killall java"); runtime.exec("killall java"); System.exit(0); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } else { logger.error("verify license success! create ok.txt file"); logger.error("verify_license OK"); } }}
/* DO NOT EDIT THIS FILE - it is machine generated */#include <jni.h>/* Header for class License */#ifndef _Included_License#define _Included_License#ifdef __cplusplusextern "C" {#endif/* * Class: License * Method: verify_license * Signature: ()Z */JNIEXPORT jboolean JNICALL Java_com_blingtel_common_util_License_verifylicense (JNIEnv *, jobject);#ifdef __cplusplus}#endif#endif
#include <stdio.h>#include <string.h>#include <sys/ioctl.h>#include <net/if.h>#include <errno.h>#include "base64.h"#include "rsa.h"#include <jni.h>#include "License.h"#define KEY_LEN 128#define RSA_N "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx""xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx""xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx""xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx""xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx""xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx""xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx""xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"#define RSA_E "010001"#pragma GCC push_options#pragma GCC optimize ("O0")int verify_license();/* Header for class IntArray */#ifdef __cplusplusextern "C" {#endifJNIEXPORT jboolean JNICALL Java_com_blingtel_common_util_License_verifylicense (JNIEnv * env, jobject job){ return verify_license();}#ifdef __cplusplus}#endif