LinkageError包括其子类,是Java中比较不应该出现的Error。出现这
些问题,大概有几个问题:ClassLoader没有严格遵守Java中默认的双亲委派模式;全限定名相同的两个类在不同的CL中有重复;程序运行时使用
的类的版本与开发时候不一样(类有变化,比如改了方法的可见性等)。
而LinkageError本身则更少见。当遇到LinkageError loader (instance of xxx)
previously initiated loading for a different type with name
"lib/MyData"时,可以肯定系统中有ClassLoader违背了Parent Delegate的规则。
问题的根源就是,当一个类已经被解析过之后,它用到的其它类也就已经确定并被解析好了。这时候,如果另一个CL也加载了同一个类(类名相同),并尝
试将这个类的实例给前面的引用赋值,因为实际上两个类是由不同的类加载器加载的,既在JVM看来是不同的类,所以就会出现这个错误。
下面是一个简单的例子。没有实际意义,只为了展示问题。
系统中的几个角色类:
IFac - 接口,提供一个getMyData方法。
MyData - 数据类,没有实际意义,但是在系统中,这个类的加载则是引发问题的关键
IFacImpl - IFac接口的实现。
系统中还有一个不可或缺的角色——
那个不遵守规则的ClassLoader
。我们需要自己写一个ClassLoader
来违法Parent Delegate
的规则。
1
package
webcl;
2
3
import
java.net.URL;
4
import
java.net.URLClassLoader;
5
import
java.net.URLStreamHandlerFactory;
6
7
public
class
WebAppCL
extends
URLClassLoader {
8
9
public
WebAppCL(URL[] urls,
ClassLoader parent,
10
URLStreamHandlerFactory factory) {
11
super
(urls, parent, factory);
12
}
13
14
public
WebAppCL(URL[] urls, ClassLoader parent) {
15
super
(urls, parent);
16
}
17
18
public
WebAppCL(URL[] urls) {
19
super
(urls);
20
}
21
22
@Override
23
protected
synchronized
Class<?> loadClass(String name,
boolean
resolve)
24
throws
ClassNotFoundException {
25
try
{
26
return
findClass(name);
27
}
catch
(ClassNotFoundException ex) {
28
return
super
.loadClass(name, resolve);
29
}
30
}
31
32
}
这个ClassLoader
唯一的作用就是违反PD
的规则。
然后是App
程序:
1
package
test;
2
3
import
java.net.URL;
4
5
import
lib.IFac;
6
import
lib.MyData;
7
import
webcl.WebAppCL;
8
public
class
App2 {
//
应用程序的classpath
上有IFac
类和MyData
类。
9
public
static
void
main(String[] args)
throws
Exception {
10
MyData resolved =
new
MyData();
11
WebAppCL cl =
new
WebAppCL(
new
URL[] {
12
new
URL("file:\\C:\\Users\\zangmeng\\Desktop\\data.jar"),
//
包含MyData
类
13
new
URL("file:\\C:\\Users\\zangmeng\\Desktop\\faclib.jar")
});
//
包含FacImpl
类,不包含IFac
类。
14
IFac fac = (IFac)
cl.loadClass("faclib.FacImpl").newInstance();
15
MyData data = fac.getData();
16
}
17
}
程序在运行时,类加载情况如下所示:
程序很简单,四行代码而已。
第一行是创建一个MyData的实例。目的是让MyData类被加载和解析。
第二行是创建一个WebAppCL,这个不听话的CL会优先加载自己classpath下的类,如果失败了再去问parent cl要。现在这个CL可以加载MyData类和FacImpl类。
第三行,首先是IFac
fac这段。JVM需要使用当前类加载器,也就是AppClassLoader,加载并解析IFac类,解析的过程中,同时链接到AppCL加载的
MyData类。等号的另一边,通过WebCl加载并创建一个FacImpl的实例。这个时候,因为WebAppCL会首先从自己的CP里加载类,所以在
解析FacImpl的时候,加载MyData的请求并没有被委派到AppCL,而是自己自己消化了,这时候JVM里面就有两个MyData类了。但是程序
到这里并没有错误,因为WebAppCL里面并没有IFac接口,这个接口还是AppCL的,但是这时候隐患已经埋下了——
FacImpl类在解析的时候,需要MyData类,而这个MyData类是被WebCL加载的。
IFac则不同,它的MyData类是被AppCL加载的。
FacImpl实现了IFac接口,按说getMyData方法应该返回相同的类型。而在runti的时候,这两个MyData却是不同的类型,因为它们是被不同的CL加载的。
第四行是引起错误的地方。等号左边的MyData实际上是第一行中那个被AppCL加载的类的一个引用。等号右边返回的MyData实例是被WebCL加载的MyData的实例。两个不同的类型,赋值自然会引发错误。
分享到:
相关推荐
NULL 博文链接:https://utopialxw.iteye.com/blog/1138133
LinkageError如何解决.md
LinkageError解决办法.md
启动Tomcat时报错:Caused by: java.lang.LinkageError: loader constraints violated when linking javax/el/ExpressionFactory class 说明:原因是juel.jar, juel-engine.jar, juel-impl.jar包和Tomcat6.0中的el-...
LinkageError(解决方案).md
el-api,java jar包,el表达式所需要的jar包。java.lang.LinkageError: loader constraints violated when linking javax/el/ExpressionFactory class;jar包冲突
项目中碰到的,记录一下
每个人都知道黑客只在晚上工作,所以多年来人们要求 PortSwigger 实现一个黑暗主题。当他们这样做时,黑客们到处欢欣鼓舞!但是,有些人仍然想要更多......直到...... Burp Customizer! Burp Suite 2020.12 用 ...
Burpsuite永久使用版,没有使用限制,V1.7.26版本,http抓包工具。
3. `javax.servlet.ServletException: java.lang.LinkageError: loader constraint violation`: 这个错误是由于两个不同的类加载器加载了同一个类的不同版本,导致签名冲突。解决方法是统一项目和Tomcat服务器中的库...
在Java中,如果不同库之间存在版本冲突,可能会导致`java.lang.LinkageError`,特别是涉及到Java API的更新时,如JAXB或JAX-WS。 描述中提到,将解压后的jar包放置在`%TOMCAT_HOME%`和`%JAVA_HOME%\lib\endorsed`...
### JBoss管理与开发之JBoss JMX实现架构详解 #### 一、引言 JBoss作为一款流行的开源应用服务器,提供了丰富的功能和支持多种企业级应用程序的部署与管理。JBoss JMX(Java Management Extensions)实现架构是...
javax.servlet.ServletException: java.lang.LinkageError
而JAXB(Java Architecture for XML Binding)是Java平台的标准,用于将XML数据与Java对象之间进行绑定,使得开发者可以方便地在XML文档和Java对象之间转换。在处理CXF与JAXB的集成时,有时会遇到版本冲突的问题,...