/** * Simple library class for working with JNI (Java Native Interface) * * @see http://frommyplayground.com/how-to-load-native-jni-library-from-jar * * @author Adam Heirnich <[email protected]>, http://www.adamh.cz */ public class NativeUtils {
/** * Private constructor - this class will never be instanced */ private NativeUtils() { }
/** * Loads library from current JAR archive * * The file from JAR is copied into system temporary directory and then loaded. The temporary file is deleted after exiting. * Method uses String as filename because the pathname is "abstract", not system-dependent. * * @param filename The filename inside JAR as absolute path (beginning with '/'), e.g. /package/File.ext * @throws IOException If temporary file creation or read/write operation fails * @throws IllegalArgumentException If source file (param path) does not exist * @throws IllegalArgumentException If the path is not absolute or if the filename is shorter than three characters (restriction of {@see File#createTempFile(java.lang.String, java.lang.String)}). */ public static void loadLibraryFromJar(String path) throws IOException {
if (!path.startsWith("/")) { throw new IllegalArgumentException("The path to be absolute (start with '/')."); }
// Check if the filename is okay if (filename == null || prefix.length() < 3) { throw new IllegalArgumentException("The filename has to be at least 3 characters long."); }
if (!temp.exists()) { throw new FileNotFoundException("File " + temp.getAbsolutePath() + " does not exist."); }
// Prepare buffer for data copying byte[] buffer = new byte[1024]; int readBytes;
// Open and check input stream InputStream is = NativeUtils.class.getResourceAsStream(path); if (is == null) { throw new FileNotFoundException("File " + path + " was not found inside JAR."); }
// Open output stream and copy data between source file in JAR and the temporary file OutputStream os = new FileOutputStream(temp); try { while ((readBytes = is.read(buffer)) != -1) { os.write(buffer, 0, readBytes); } } finally { // If read/write fails, close streams safely before throwing an exception os.close(); is.close(); }
// Finally, load the library System.load(temp.getAbsolutePath()); } }
版主,你这个NativeUtils 是要打成jar包吗?我直接调用报错! was not found inside JAR!
不需要,跟你调用 jni 的类放一起即可
import java.io.IOException; /////////////////////////////////////////////////////// // GrandDog.java // // Contains class GrandDog defining variables and native methods to // interface with DOG device driver. // // Copyright (C) 2010 SafeNet China Ltd. // ///////////////////////////////////////////////////////public class JGrandDog { public native long RC_OpenDog(long lFlag, byte bszProductName[],long lDogHandle[]); public native long RC_CheckDog(long lDogHandle); public native long RC_GetDogInfo(long lDogHandle,RC_HARDWARE_INFO sHardwareInfo, long lOutLen[]); public native long RC_GetProductCurrentNo(long lDogHandle,long lProductCurrentNo[]); public native long RC_CloseDog(long lDogHandle); public native long RC_VerifyPassword(long lDogHandle, byte bPasswordType,byte bszPassword[], byte bDegree[]); public native long RC_ChangePassword(long lDogHandle, byte bPasswordType,byte bszPassword[]); public native long RC_GetUpgradeRequestString(long lDogHandle, byte bBuf[],long lLen[]); public native long RC_Upgrade(long lDogHandle, byte bUpgrade[], long lLen); public native long RC_GetRandom(long lDogHandle, byte bRandom[], byte bLen); public native long RC_EncryptData(long lDogHandle, byte bIn[], long lInLen,byte bOut[], long lOutLen[]); public native long RC_DecryptData(long lDogHandle, byte bIn[], long lInLen,byte bOut[], long lOutLen[]); public native long RC_ConvertData(long lDogHandle, byte bIn[], long lLen,long lRet[]); public native long RC_SetKey(long lDogHandle, byte bKeyType, byte bIn[],long lLen); public native long RC_SignData(long lDogHandle, byte bIn[], long lLen,byte bOut[], long lOutLen[]); public native long RC_ExecuteFile(long lDogHandle, short sDirID,short sFileID, byte bDataIn[], long lInLen, byte bDataOut[],long lOutLen[]); public native long RC_ReadFile(long lDogHandle, short sDirID,short sFileID, long lPos, long lLen, byte bBuf[]); public native long RC_WriteFile(long lDogHandle, short sDirID,short sFileID, long lPos, long lLen, byte bBuf[]); public native long RC_VisitLicenseFile(long lDogHandle, short sDirID,short sFileID, long lReserved); public native long RC_CreateFile(long lDogHandle, short sDirID,short sFileID, byte bFileType, long lFileLen); public native long RC_DeleteFile(long lDogHandle, short sDirID,short sFileID); public native long RC_CreateDir(long lDogHandle, short sDirID, long lSize); public native long RC_DeleteDir(long lDogHandle, short sDirID); public native long RC_DefragFileSystem(long lDogHandle, short sDirID); public native long RC_GetLicenseInfo(long lDogHandle, short sDirID,short sFileID, RC_LICENSE_INFO sLicInfo); static { System.out.println(1); System.loadLibrary("libgrandlinuxj_64"); } catch (UnsatisfiedLinkError e) { System.out.println(e); try { NativeUtils.loadLibraryFromJar("/usr/local/dog/libgrandlinuxj_64.so"); // during runtime. .DLL within .JAR } catch (IOException e1) { throw new RuntimeException(e1); } System.exit(-1); } } } 版主,我初始化这个类的时候报错!java.lang.UnsatisfiedLinkError: no libgrandlinuxj_64 in java.library.path java.lang.reflect.InvocationTargetException at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) at ykxx.trial.service.impl.DBServiceImpl.selectMore(Unknown Source) at ykxx.trial.service.lllIIIllIIlIIllI.getResult(Unknown Source) at ykxx.trial.service.lllIIIllIIlIIllI.getResult(Unknown Source) at org.apache.thrift.ProcessFunction.process(ProcessFunction.java:32) at org.apache.thrift.TBaseProcessor.process(TBaseProcessor.java:34) at org.apache.thrift.server.TServlet.doPost(TServlet.java:83) at javax.servlet.http.HttpServlet.service(HttpServlet.java:153) at javax.servlet.http.HttpServlet.service(HttpServlet.java:91) at com.caucho.server.dispatch.ServletFilterChain.doFilter(ServletFilterChain.java:103) at com.caucho.server.webapp.WebAppFilterChain.doFilter(WebAppFilterChain.java:187) at com.caucho.server.dispatch.ServletInvocation.service(ServletInvocation.java:265) at com.caucho.server.http.HttpRequest.handleRequest(HttpRequest.java:273) at com.caucho.server.port.TcpConnection.run(TcpConnection.java:682) at com.caucho.util.ThreadPool$Item.runTasks(ThreadPool.java:743) at com.caucho.util.ThreadPool$Item.run(ThreadPool.java:662) at java.lang.Thread.run(Thread.java:662) Caused by: java.lang.ExceptionInInitializerError at DT.checkFlag(DT.java:22) ... 20 more Caused by: java.lang.RuntimeException: java.io.FileNotFoundException: File /usr/local/dog/libgrandlinuxj_64.so was not found inside JAR. at JGrandDog.<clinit>(JGrandDog.java:93) ... 21 more Caused by: java.io.FileNotFoundException: File /usr/local/dog/libgrandlinuxj_64.so was not found inside JAR. at NativeUtils.loadLibraryFromJar(NativeUtils.java:73) at JGrandDog.<clinit>(JGrandDog.java:91) ... 21 more
版主我看了你的那个源码, InputStream is = NativeUtils.class.getResourceAsStream(path);这个path是相对于tomcat目录下的的绝对路径,但是我穿入目录是/webapps/host/WEB-INF/classes/xxx.so还是不行! 还是报错java.lang.RuntimeException: java.io.FileNotFoundException: File /webapps/host/WEB-INF/classes/com/ykxx/host/web/dog/libgrandlinuxj_64.so was not found inside JAR.
你开发测试的时候是 eclipse,System.loadLibrary("xxxx") 加载,当然没问题。
但是部署以后,System.loadLibrary("xxxx") 就不行了,你需要这样:
static {
try {
System.loadLibrary("crypt"); // used for tests. This library in classpath only
} catch (UnsatisfiedLinkError e) {
try {
NativeUtils.loadLibraryFromJar("/natives/crypt.dll"); // during runtime. .DLL within .JAR
} catch (IOException e1) {
throw new RuntimeException(e1);
}
}
}NativeUtils 源码参考:package cz.adamh.utils;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
/**
* Simple library class for working with JNI (Java Native Interface)
*
* @see http://frommyplayground.com/how-to-load-native-jni-library-from-jar
*
* @author Adam Heirnich <[email protected]>, http://www.adamh.cz
*/
public class NativeUtils {
/**
* Private constructor - this class will never be instanced
*/
private NativeUtils() {
}
/**
* Loads library from current JAR archive
*
* The file from JAR is copied into system temporary directory and then loaded. The temporary file is deleted after exiting.
* Method uses String as filename because the pathname is "abstract", not system-dependent.
*
* @param filename The filename inside JAR as absolute path (beginning with '/'), e.g. /package/File.ext
* @throws IOException If temporary file creation or read/write operation fails
* @throws IllegalArgumentException If source file (param path) does not exist
* @throws IllegalArgumentException If the path is not absolute or if the filename is shorter than three characters (restriction of {@see File#createTempFile(java.lang.String, java.lang.String)}).
*/
public static void loadLibraryFromJar(String path) throws IOException {
if (!path.startsWith("/")) {
throw new IllegalArgumentException("The path to be absolute (start with '/').");
}
// Obtain filename from path
String[] parts = path.split("/");
String filename = (parts.length > 1) ? parts[parts.length - 1] : null;
// Split filename to prexif and suffix (extension)
String prefix = "";
String suffix = null;
if (filename != null) {
parts = filename.split("\\.", 2);
prefix = parts[0];
suffix = (parts.length > 1) ? "."+parts[parts.length - 1] : null; // Thanks, davs! :-)
}
// Check if the filename is okay
if (filename == null || prefix.length() < 3) {
throw new IllegalArgumentException("The filename has to be at least 3 characters long.");
}
// Prepare temporary file
File temp = File.createTempFile(prefix, suffix);
temp.deleteOnExit();
if (!temp.exists()) {
throw new FileNotFoundException("File " + temp.getAbsolutePath() + " does not exist.");
}
// Prepare buffer for data copying
byte[] buffer = new byte[1024];
int readBytes;
// Open and check input stream
InputStream is = NativeUtils.class.getResourceAsStream(path);
if (is == null) {
throw new FileNotFoundException("File " + path + " was not found inside JAR.");
}
// Open output stream and copy data between source file in JAR and the temporary file
OutputStream os = new FileOutputStream(temp);
try {
while ((readBytes = is.read(buffer)) != -1) {
os.write(buffer, 0, readBytes);
}
} finally {
// If read/write fails, close streams safely before throwing an exception
os.close();
is.close();
}
// Finally, load the library
System.load(temp.getAbsolutePath());
}
}
///////////////////////////////////////////////////////
// GrandDog.java
//
// Contains class GrandDog defining variables and native methods to
// interface with DOG device driver.
//
// Copyright (C) 2010 SafeNet China Ltd.
//
///////////////////////////////////////////////////////public class JGrandDog {
public native long RC_OpenDog(long lFlag, byte bszProductName[],long lDogHandle[]); public native long RC_CheckDog(long lDogHandle); public native long RC_GetDogInfo(long lDogHandle,RC_HARDWARE_INFO sHardwareInfo, long lOutLen[]); public native long RC_GetProductCurrentNo(long lDogHandle,long lProductCurrentNo[]); public native long RC_CloseDog(long lDogHandle); public native long RC_VerifyPassword(long lDogHandle, byte bPasswordType,byte bszPassword[], byte bDegree[]); public native long RC_ChangePassword(long lDogHandle, byte bPasswordType,byte bszPassword[]); public native long RC_GetUpgradeRequestString(long lDogHandle, byte bBuf[],long lLen[]); public native long RC_Upgrade(long lDogHandle, byte bUpgrade[], long lLen); public native long RC_GetRandom(long lDogHandle, byte bRandom[], byte bLen); public native long RC_EncryptData(long lDogHandle, byte bIn[], long lInLen,byte bOut[], long lOutLen[]); public native long RC_DecryptData(long lDogHandle, byte bIn[], long lInLen,byte bOut[], long lOutLen[]); public native long RC_ConvertData(long lDogHandle, byte bIn[], long lLen,long lRet[]); public native long RC_SetKey(long lDogHandle, byte bKeyType, byte bIn[],long lLen); public native long RC_SignData(long lDogHandle, byte bIn[], long lLen,byte bOut[], long lOutLen[]); public native long RC_ExecuteFile(long lDogHandle, short sDirID,short sFileID, byte bDataIn[], long lInLen, byte bDataOut[],long lOutLen[]); public native long RC_ReadFile(long lDogHandle, short sDirID,short sFileID, long lPos, long lLen, byte bBuf[]); public native long RC_WriteFile(long lDogHandle, short sDirID,short sFileID, long lPos, long lLen, byte bBuf[]); public native long RC_VisitLicenseFile(long lDogHandle, short sDirID,short sFileID, long lReserved); public native long RC_CreateFile(long lDogHandle, short sDirID,short sFileID, byte bFileType, long lFileLen); public native long RC_DeleteFile(long lDogHandle, short sDirID,short sFileID); public native long RC_CreateDir(long lDogHandle, short sDirID, long lSize); public native long RC_DeleteDir(long lDogHandle, short sDirID); public native long RC_DefragFileSystem(long lDogHandle, short sDirID); public native long RC_GetLicenseInfo(long lDogHandle, short sDirID,short sFileID, RC_LICENSE_INFO sLicInfo); static {
System.out.println(1);
System.loadLibrary("libgrandlinuxj_64");
} catch (UnsatisfiedLinkError e) {
System.out.println(e);
try {
NativeUtils.loadLibraryFromJar("/usr/local/dog/libgrandlinuxj_64.so"); // during runtime. .DLL within .JAR
} catch (IOException e1) {
throw new RuntimeException(e1);
}
System.exit(-1);
}
}
}
版主,我初始化这个类的时候报错!java.lang.UnsatisfiedLinkError: no libgrandlinuxj_64 in java.library.path
java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at ykxx.trial.service.impl.DBServiceImpl.selectMore(Unknown Source)
at ykxx.trial.service.lllIIIllIIlIIllI.getResult(Unknown Source)
at ykxx.trial.service.lllIIIllIIlIIllI.getResult(Unknown Source)
at org.apache.thrift.ProcessFunction.process(ProcessFunction.java:32)
at org.apache.thrift.TBaseProcessor.process(TBaseProcessor.java:34)
at org.apache.thrift.server.TServlet.doPost(TServlet.java:83)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:153)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:91)
at com.caucho.server.dispatch.ServletFilterChain.doFilter(ServletFilterChain.java:103)
at com.caucho.server.webapp.WebAppFilterChain.doFilter(WebAppFilterChain.java:187)
at com.caucho.server.dispatch.ServletInvocation.service(ServletInvocation.java:265)
at com.caucho.server.http.HttpRequest.handleRequest(HttpRequest.java:273)
at com.caucho.server.port.TcpConnection.run(TcpConnection.java:682)
at com.caucho.util.ThreadPool$Item.runTasks(ThreadPool.java:743)
at com.caucho.util.ThreadPool$Item.run(ThreadPool.java:662)
at java.lang.Thread.run(Thread.java:662)
Caused by: java.lang.ExceptionInInitializerError
at DT.checkFlag(DT.java:22)
... 20 more
Caused by: java.lang.RuntimeException: java.io.FileNotFoundException: File /usr/local/dog/libgrandlinuxj_64.so was not found inside JAR.
at JGrandDog.<clinit>(JGrandDog.java:93)
... 21 more
Caused by: java.io.FileNotFoundException: File /usr/local/dog/libgrandlinuxj_64.so was not found inside JAR.
at NativeUtils.loadLibraryFromJar(NativeUtils.java:73)
at JGrandDog.<clinit>(JGrandDog.java:91)
... 21 more
你去好好看看 NativeUtils 的源码,读懂了就知道该怎么做了
还是报错java.lang.RuntimeException: java.io.FileNotFoundException: File /webapps/host/WEB-INF/classes/com/ykxx/host/web/dog/libgrandlinuxj_64.so was not found inside JAR.
如果你的动态库的文件名是libgrandlinuxj_64.so,应该用loadLibrary("grandlinuxj_64")
如果还不行,你用load("这里填文件的绝对路径")
java.lang.UnsatisfiedLinkError: com.ykxx.host.web.dog.JGrandDog.RC_OpenDog(J[B[J)J
com.ykxx.host.web.dog.JGrandDog.RC_OpenDog(Native Method)
com.ykxx.host.web.dog.J2sdkDemo.checkFlag(J2sdkDemo.java:54)
com.ykxx.host.web.LoginAction.doAction(LoginAction.java:42)
com.ykxx.host.web.BaseAction.handleRequest(BaseAction.java:42)
org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter.handle(SimpleControllerHandlerAdapter.java:48)
org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:923)
org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:852)
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:882)
org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:789)
javax.servlet.http.HttpServlet.service(HttpServlet.java:643)
javax.servlet.http.HttpServlet.service(HttpServlet.java:723)
然后直接load据对路径有什么区别?
这个错误是因为你的 JGrandDog 类放错了包。这个你要看加密狗的文档。
如果没有文档,linux有个命令可以看动态库导出的函数(好像是nm)。
_Java_sun_reflect_ConstantPool_getFieldAt0@16
上面这个函数表示链接的是包 sun.reflect 的类 ConstantPool 的 getFieldAt 方法。
你把 JGrandDog 放到正确的包看看。 至于 loadLibrary 还是找不到库。
你看下 System.mapLibraryName("grandlinuxj_64") 是不是 "libgrandlinuxj_64.so"
然后根据规则反推一个正确的 libname。
如果还不行,你只能看当前的 ClassLoader.findLibrary(String libname) 的源码了。