java调用dll异常的处理(UnsatisfiedLinkError)

背景描述

因业务需要,java项目需要调用dll进行MD5加密处理。dll是其它项目组提供的,基于64位平台编译的;java项目是基于maven的。
我把dll文件放在resources目录下,相关代码如下:
加载dll方法的类:
public class NativeMethod{

public native String getC4MD5(String pwd);

public String getC4MD51(String pwd){
String filePath = this.getClass().getClassLoader().getResource("/").getPath();
filePath +="Md5.dll";
try {
filePath = java.net.URLDecoder.decode(filePath, "utf-8");
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
filePath = filePath.startsWith("/") ? filePath.substring(1) : filePath;
        File file=new File(filePath.replaceAll("/", "\\\\"));
System.load(file.toString());
return getC4MD5(pwd);
}

}

调用方式:

public Map<String,Object> doLogin(String userName,String password){
Map<String,Object> resultMap = new HashMap<String,Object>();
try {
NativeMethod n =  new NativeMethod();
String pwd = n.getC4MD51(password);
System.out.println("pwd:" + pwd);
resultMap.put("pwd", pwd);
} catch (Exception e) {
e.printStackTrace();
resultMap.put("result", false);
resultMap.put("error", e);
}
return resultMap;
}


问题描述

接下来记录调用过程中碰到的两个主要问题:
1.JDK版本问题,由于dll是64位的,而我的JDK是32位的,所以会报平台兼容性的错误。解决方案就是把JDK替换成64位版本的。这方面的资料百度上一搜一大堆,这里就不作展开。
2.JDK版本替换成64位之后,通过myeclipse直接部署到tomcat上,可以正常运行,调用加密方法也正常。以为大功告成,于是通过maven打成war,部署到服务器上,结果报错:
2017-04-19 11:37:54  [ http-bio-8080-exec-10:10988 ] - [ DEBUG ]  Could not complete request
org.springframework.web.util.NestedServletException: Handler processing failed; nested exception is java.lang.UnsatisfiedLinkError: D:\Program Files\Apache Software Foundation\Tomcat 7.0\webapps\bss\WEB-INF\classes\Md5.dll: Can't load this .dll (machine code=0xbd) on a AMD 64-bit platform
at org.springframework.web.servlet.DispatcherServlet.triggerAfterCompletionWithError(DispatcherServlet.java:1302)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:977)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:893)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:968)
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:859)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:624)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:844)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:731)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at com.alibaba.druid.support.http.WebStatFilter.doFilter(WebStatFilter.java:123)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:121)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:218)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:122)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:505)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:169)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:956)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:442)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1082)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:623)
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:318)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Unknown Source)

奇怪啊,本地跑的好好的,怎么到服务器上就不行了呢?百思不得其解。


解决方案

折腾了好久,最后在stackoverflow上找到了解决方法。
参考链接:http://stackoverflow.com/questions/38244970/running-my-generated-jar-yields-cant-load-this-dll-machine-code-0xbd-on-a

原文如下:

I experienced the same problem when I tried to run the JAR that was built by Maven (but with a 32 bit DLL - Can't load this .dll (machine code=0xbd) on a IA 32-bit platform). Strange thing was: It happened after I moved the DLL in a folder with other resources which have to be copied during the build.

I took me a quite a while to find out that the maven resources plugin was changing the DLL file for some reason (might be a bug?). The original DLL file is 76 kb - the copied DLL in the target folder was 118 kb. Something happened to the file during build.

Adding an extra execution to copy the DLL files without <filtering>true</filtering> solved the problem.

根据这位大神的描述,是maven在打包的时候对dll做了某种不可知的修改,导致修改后的dll无法使用。
我把war包里的dll文件取出来和原文件一比较,果然如此:原文件123k,war取出来的195k,确实是maven引起的问题。
再查看maven工程的pom.xml,打包相关配置如下:
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
<includes>
<include>**/*.xml</include>
<include>**/*.properties</include>
<include>**/*.dll</include>
</includes>
</resource>

然后根据这位大神说的,把filtering注释掉,改成如下:
<resource>
<directory>src/main/resources</directory>
<!-- <filtering>true</filtering>
<includes>
<include>**/*.xml</include>
<include>**/*.properties</include>
<include>**/*.dll</include>
</includes> -->
</resource>

再次编译,问题解决。
或许,如这位大神所说,这真的是maven的一个bug吧。
  • 1
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值