java.lang.UnsatisfiedLinkError解决方法汇集
来源:互联网 发布:易语言2017盗号源码 编辑:程序博客网 时间:2024/06/08 16:09
运行JSP报表程序页面出现java.lang.UnsatisfiedLinkError: CC错误有以下几种原因和处理方法:
1、请查看控制台的错误信息
a:如果控制台的消息是类似
java.lang.UnsatisfiedLinkError: no MRChkLib in java.library.path,Error loading library MRChkLib
这样的错误信息,那么是因为MRChkLib.dll没有拷贝到windows的System32目录下. (MRChkLib.dll是加密锁的JAVA接口文件,文件在报表安装目录DogDriver\JavaAPI下可以找到) 并且要注意PATH环境变量中要包含System32目录。(如果服务器操作系统是Linux,那么使用报表安装目录DogDriver\JavaAPI下的libMRChkLib.so文件,将libMRChkLib.so复制到WebServer的启动bin目录。如果在这个目录下仍然出现can not load library错误,请设置系统环境变量LD_LIBRARY_PATH的值为libMRChkLib.so所在的目录。
例如:如果libMRChkLib.so在/somedir目录下,则 export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/somedir)
b:如果控制台的消息是类似
java.lang.unsatisfiedLinkError :native libery c:\winnt\system32\mrchklib.dll already loaded in another classLoader error loading mrchklib.dll
这样的错误信息,那么是因为WebAPP在重新被启动之后,无法再次加载动态库造成的,这是java的约束,Java不允许一个实例加载多次动态库.可以这样解决,将mr.jar拷贝到WebServer的lib目录,删除/WEB-INF/lib目录下的mr.jar,然后重新启动webserver。
2、如果一个webserver上有多个报表应用,请将/WEB-INF/lib/mr.jar移动到WebServer的lib目录下,确保每一个Web应用程序目录下都没有mr.jar,而只有WebServer的lib目录下有该文件,重启webserver.
3、一个Webserver上只能有一个mr.jar文件,删掉多余的mr*.jar文件,然后清除webserver临时文件,重新启动webserver。
Exception in thread "main" java.lang.UnsatisfiedLinkError: HelloWorld.print()V
奇怪了,loadLibrary()没有问题,怎么会找不到方法呢?用dll export viewer察看,导出的方法为
函数名 地址 偏移量
Java_HelloWorld_print@8 0x67741250 0x00001250
实在没办法了,只好安装庞大的visual studio重新来编译,调用成功了!
再次用dll export viewer查看,发现函数名的前面多了一条下划线
函数名 地址 偏移量
_Java_HelloWorld_print@8 0x67741250 0x00001250
看来是给MinGW少传了某个参数,经过网上查阅资料,终于找到一个解决方案:给MinGW的ld命令指定一个参数--kill-at即可
gcc -Wl, --kill-at -shared -o jnihello.dll HelloWorld.c
再次用dll export viewer查看,发现导出的函数名称变为
函数名 地址 偏移量
Java_HelloWorld_print 0x67741250 0x00001250
--kill-at指令去掉了函数名称后缀的@,并没有像msvc那样添加前缀的下划线
UnsatisfiedLinkError
在把本机调用链接到对应的本机定义时,类装入器扮演着重要角色。如果程序试图装入一个不存在或者放错的本机库时,在链接阶段的解析过程会发生 UnsatisfiedLinkError
。JVM 规范指定 UnsatisfiedLinkError
是:
对于声明为 native
的方法,如果 Java 虚拟机找不到和它对应的本机语言定义,就会抛出该异常。
当调用本机方法时,类装入器会尝试装入定义了该方法的本机库。如果找不到这个库,就会抛出这个错误。
清单 6 演示了抛出 UnsatisfiedLinkError
的测试用例 :
清单 6. UnsatisfiedLinkError.java
public class UnsatisfiedLinkErrorTest { public native void call_A_Native_Method(); static { System.loadLibrary("myNativeLibrary"); } public static void main(String[] args) { new UnsatisfiedLinkErrorTest().call_A_Native_Method(); } }
这段代码调用本机方法 call_A_Native_Method()
,该方法是在本机库 myNativeLibrary
中定义的。因为这个库不存在,所以在程序运行时会发生以下错误:
The java class could not be loaded. java.lang.UnsatisfiedLinkError: Cant find library myNativeLibrary (myNativeLibrary.dll) in sun.boot.library.path or java.library.path sun.boot.library.path=D:\sdk\jre\bin java.library.path= D:\sdk\jre\bin at java.lang.ClassLoader$NativeLibrary.load(Native Method) at java.lang.ClassLoader.loadLibrary0(ClassLoader.java:2147) at java.lang.ClassLoader.loadLibrary(ClassLoader.java:2006) at java.lang.Runtime.loadLibrary0(Runtime.java:824) at java.lang.System.loadLibrary(System.java:908) at UnsatisfiedLinkErrorTest.<clinit>(UnsatisfiedLinkErrorTest.java:6)
本机库的装入由调用 System.loadLibrary()
方法的类的类装入器启动 —— 在清单 6 中,就是 UnsatisfiedLinkErrorTest
的类装入器。根据使用的类装入器,会搜索不同的位置:
- 对于由 bootstrap 类装入器装入的类,搜索
sun.boot.library.path
。 - 对于由扩展类装入器装入的类,先搜索
java.ext.dirs
,然后是sun.boot.library.path
,然后是java.library.path
。 - 对于由系统类装入器装入的类,搜索
sun.boot.library.path
,然后是java.library.path
。
在清单 6 中,UnsatisfiedLinkErrorTest
类是由系统类装入器装入的。要装入所引用的本机库,这个类装入器先查找 sun.boot.library.path
,然后查找 java.library.path
。因为在两个位置中都没有需要的库,所以类装入器抛出 UnsatisfiedLinkageError
。
java.lang.UnsatisfiedLinkError出现这种错误的原因是一般是java虚拟机找不到声明为native方法的本地语言定义时,出现的错误。在我的理解过程中我一般都认为是由于导入dll或者导入lib文件不正确导致的。有些需要静态导入就没有问题(即在前面加static来导入lib文件),如果是不加static导入也就是动态导入的时候,那么需要添加catch的抛出异常来解决,如
try{
System.loadLibrary("vtkCommonJava");
System.loadLibrary("vtkFilteringJava");
System.loadLibrary("vtkIOJava");
System.loadLibrary("vtkImagingJava");
System.loadLibrary("vtkGraphicsJava");
System.loadLibrary("vtkRenderingJava");
}catch(Throwable e)
{
System.out.println("The load problem");
}
这种方式来判断,或者直接在类前面添加
static{
System.loadLibrary("vtkCommonJava");
System.loadLibrary("vtkFilteringJava");
System.loadLibrary("vtkIOJava");
System.loadLibrary("vtkImagingJava");
System.loadLibrary("vtkGraphicsJava");
System.loadLibrary("vtkRenderingJava");
背景:GEM(1)有一堆java包和native函数,pbp1.0是虚拟机和JAVA基本包,要将pbp1.0的虚拟机移走只用它的JAVA基本包和native函数。
问题:在将GEM和pbp1.0的native函数生成一个动态库后在程序里System.loadLibrary()无法加载,报java.lang.UnsatisfiedLinkError
解决过程:
1,理论
我们知道,JAVA调用native函数时,必须通过System.loadLibrary()或System.load将其native函数所在动态库加载到虚拟机。并在运行时指明-Djava.library.path或-Dsun.boot.library.path,将其指向包含有native函数的动态库所在位置。
2,实施
我按这个步骤操作完成后就是无法加载我生成的动态库libgem.so,这个库用到的其他动态库包括:rt,pthread,freetype,dl,directfb,而directfb用到的动态库有rt,dl,pthread,freetype,jpeg,png,这些库除了directfb要生成外其余都在/lib目录下存在。
3,思路
先写了一个Hello的测试用例。发现在native里所使用到其他动态库时,无论是否存在于相关目录,仍然无法加载。然后经过修改编译选项,把所使用到的动态库连动态连接进目标库,如下:
$(GCC) -fPIC -shared -o libdirectfb.so ... -lpng -ljpeg -lpthread -lrt -ldl, -lfreetype
经过这么一个修改后,directfb可以加载。
这也说明System.loadLibrary()所加载的动态库所引用的所有符号都要能找到。如果有一个无法找到将无法加载。可以写一个空的main()函数,对你的动态库进行连接,如果动态库里所引用的符号在指定的动态库和本身找到不到则无法编译通过,那么这个动态库也肯定加载不了。
4,问题解决
按照这个思路,对libgem.so的编译Makefile做相应修改后,问题解决!并在LD_LIBRARY_PATH加入动态库所在目录。
(1) MHP (Multimedia Home Platform) was developed by the DVB Project as the world's first open standard for interactive television. It is a Java-based environment which defines a generic interface between interactive digital applications and the terminals on which those applications execute. MHP was designed to run on DVB platforms but there was a demand to extend the interoperability it offers to other digital television platforms. This demand gave rise to GEM, or Globally Executable MHP, a framework which allows other organisations to define specifications based on MHP.
====================================================================================
另外,还可能是dll本身的问题,使用release版的,而不要用debug版的
关于编写JNI时的发生的unsatisfiedlinkError错误- -
这个错误也让我郁闷了半天,现在我把它写出来,可以让大家少走点弯路。一般这个错误有两种:
1。unsatisfiedlinkError:dll名,那说明你没有把dll放到合适的位置,一般就和要调用原生函数的类放在一起,当然前提是你成功的生成dll了
2。unsatisfiedlinkError:方法名,这个时候你其实dll已经成功生成了,而且位置也正确,它的意思就是你没有定义那个函数,你可能会说,我明明定义了,其实当你发现问题所在,你只能自虐了,肯定是你在C文件中定义函数时有些字母大小写错了,因为其他地方是自动生成的,不会出错。尤其是直接从网上拷贝源程序时经常发生这种问题,有些作者不负责任,把有错误的程序也贴上去。
错误如下:
java.lang.UnsatisfiedLinkError: E:\Program Files\MyEclipse 10\apache-tomcat-7.0.23\bin\tcnative-1.dll: Can't load IA 32-bit .dll on a AMD 64-bit platform at java.lang.ClassLoader$NativeLibrary.load(Native Method) at java.lang.ClassLoader.loadLibrary0(ClassLoader.java:1778) at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1703) at java.lang.Runtime.loadLibrary0(Runtime.java:823) at java.lang.System.loadLibrary(System.java:1030) at org.apache.tomcat.jni.Library.<init>(Library.java:42) at org.apache.tomcat.jni.Library.initialize(Library.java:174) 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 org.apache.catalina.core.AprLifecycleListener.init(AprLifecycleListener.java:179) at org.apache.catalina.core.AprLifecycleListener.isAprAvailable(AprLifecycleListener.java:84) at org.apache.catalina.connector.Connector.setProtocol(Connector.java:567) at org.apache.catalina.connector.Connector.<init>(Connector.java:69) at org.apache.catalina.startup.ConnectorCreateRule.begin(ConnectorCreateRule.java:62) at org.apache.tomcat.util.digester.Digester.startElement(Digester.java:1276) at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.startElement(AbstractSAXParser.java:501) at com.sun.org.apache.xerces.internal.parsers.AbstractXMLDocumentParser.emptyElement(AbstractXMLDocumentParser.java:179) at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanStartElement(XMLDocumentFragmentScannerImpl.java:1339) at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl$FragmentContentDriver.next(XMLDocumentFragmentScannerImpl.java:2747) at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next(XMLDocumentScannerImpl.java:648) at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(XMLDocumentFragmentScannerImpl.java:510) at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:807) at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:737) at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:107) at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(AbstractSAXParser.java:1205) at com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl$JAXPSAXParser.parse(SAXParserImpl.java:522) at org.apache.tomcat.util.digester.Digester.parse(Digester.java:1537) at org.apache.catalina.startup.Catalina.load(Catalina.java:555) at org.apache.catalina.startup.Catalina.load(Catalina.java:598) 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 org.apache.catalina.startup.Bootstrap.load(Bootstrap.java:281) at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:449) 2013-3-29 13:18:09 org.apache.catalina.core.AprLifecycleListener init
问题所在:
主要是在64位的系统下安装的虚拟机是64位的,而WTK的sublime.dll不能在64位的平台下加载64位的虚拟机,只能加载32位的。由于WTK在安装的时候加载的64虚拟机的地址,它找到的是64位的虚拟机,所以它提示不能加载32位的虚拟机(在目录下没有32的虚拟机)
下载 the 32bit from http://www.apache.org/dist/tomcat/tomcat-connectors/native/1.1.20/binaries/ to 替换
下载时有更新变动,下载最近的即可http://www.apache.org/dist/tomcat/tomcat-connectors/native/
如下图
OK 问题解决
2013-3-29 13:22:45 org.apache.catalina.core.AprLifecycleListener init 信息: Loaded APR based Apache Tomcat Native library 1.1.27. 2013-3-29 13:22:45 org.apache.catalina.core.AprLifecycleListener init 信息: APR capabilities: IPv6 [true], sendfile [true], accept filters [false], random [true]. 2013-3-29 13:22:47 org.apache.coyote.AbstractProtocol init 信息: Initializing ProtocolHandler ["http-apr-8080"] 2013-3-29 13:22:47 org.apache.coyote.AbstractProtocol init 信息: Initializing ProtocolHandler ["ajp-apr-8009"] 2013-3-29 13:22:47 org.apache.catalina.startup.Catalina load 信息: Initialization processed in 2088 ms 2013-3-29 13:22:47 org.apache.catalina.core.StandardService startInternal 信息: Starting service Catalina 2013-3-29 13:22:47 org.apache.catalina.core.StandardEngine startInternal 信息: Starting Servlet Engine: Apache Tomcat/7.0.23 2013-3-29 13:22:47 org.apache.catalina.startup.HostConfig deployDirectory 信息: Deploying web application directory E:\Program Files\MyEclipse 10\apache-tomcat-7.0.23\webapps\docs 2013-3-29 13:22:47 org.apache.catalina.startup.HostConfig deployDirectory 信息: Deploying web application directory E:\Program Files\MyEclipse 10\apache-tomcat-7.0.23\webapps\examples 2013-3-29 13:22:48 org.apache.catalina.core.ApplicationContext log 信息: ContextListener: contextInitialized() 2013-3-29 13:22:48 org.apache.catalina.core.ApplicationContext log 信息: SessionListener: contextInitialized() 2013-3-29 13:22:48 org.apache.catalina.core.ApplicationContext log 信息: ContextListener: attributeAdded('org.apache.jasper.compiler.TldLocationsCache', 'org.apache.jasper.compiler.TldLocationsCache@4402a6ff') 2013-3-29 13:22:48 org.apache.catalina.startup.HostConfig deployDirectory 信息: Deploying web application directory E:\Program Files\MyEclipse 10\apache-tomcat-7.0.23\webapps\host-manager 2013-3-29 13:22:48 org.apache.catalina.startup.HostConfig deployDirectory 信息: Deploying web application directory E:\Program Files\MyEclipse 10\apache-tomcat-7.0.23\webapps\manager 2013-3-29 13:22:48 org.apache.catalina.startup.HostConfig deployDirectory 信息: Deploying web application directory E:\Program Files\MyEclipse 10\apache-tomcat-7.0.23\webapps\ROOT 2013-3-29 13:22:48 org.apache.coyote.AbstractProtocol start 信息: Starting ProtocolHandler ["http-apr-8080"] 2013-3-29 13:22:48 org.apache.coyote.AbstractProtocol start 信息: Starting ProtocolHandler ["ajp-apr-8009"] 2013-3-29 13:22:48 org.apache.catalina.startup.Catalina start 信息: Server startup in 1261 ms
1、问题
通过Eclipse启动Tomcat时,抛出异常java.net.SocketException: Unrecognized Windows Sockets error: 0: JVM_Bind。此异常的原因是服务器端口被占用
其解决办法包括以下两种:
一:更改服务器的端口号;
二:关闭占用当前占用该端口的进程
2、更改服务器端口号
到tomcat目录下的把conf文件夹下的server.xml文件中,找到
<Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" />
将该端口修改一下便可
<Connector port="8088" protocol="AJP/1.3" redirectPort="8443" />
3、关闭当前占用该端口的进程
1)首先进入命令行 查看端口是否被占用
使用命令: netstat -ano
我的服务器的端口是443
此端口已被PID为3432的进程占用
2)通过任务管理器或taskkill程序结束PID为3432的进程。
4、关闭当前占用该端口的进程
还有可能是因为javaw的这个进程跟tomcat的服务起冲突。可以将javaw.exe的先结束进程。再重新运行程序。