`
deepnighttwo
  • 浏览: 52129 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

LinkageError之loader (instance of xxx) previously initiated loading for a differe

 
阅读更多

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的实例。两个不同的类型,赋值自然会引发错误。

分享到:
评论

相关推荐

    Exception in thread \"main\" java.lang.LinkageError错误的解决

    NULL 博文链接:https://utopialxw.iteye.com/blog/1138133

    LinkageError如何解决.md

    LinkageError如何解决.md

    LinkageError解决办法.md

    LinkageError解决办法.md

    juel-Tomcat与EL冲突问题

    启动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

    LinkageError(解决方案).md

    el-api.jar

    el-api,java jar包,el表达式所需要的jar包。java.lang.LinkageError: loader constraints violated when linking javax/el/ExpressionFactory class;jar包冲突

    LinkageError.md

    项目中碰到的,记录一下

    Burp suite主题插件.jar

    每个人都知道黑客只在晚上工作,所以多年来人们要求 PortSwigger 实现一个黑暗主题。当他们这样做时,黑客们到处欢欣鼓舞!但是,有些人仍然想要更多......直到...... Burp Customizer! Burp Suite 2020.12 用 ...

    Burpsuite永久版

    Burpsuite永久使用版,没有使用限制,V1.7.26版本,http抓包工具。

    JBPM4运行时错误异常总结

    3. `javax.servlet.ServletException: java.lang.LinkageError: loader constraint violation`: 这个错误是由于两个不同的类加载器加载了同一个类的不同版本,导致签名冲突。解决方法是统一项目和Tomcat服务器中的库...

    endorsed 解决soa连接错误

    在Java中,如果不同库之间存在版本冲突,可能会导致`java.lang.LinkageError`,特别是涉及到Java API的更新时,如JAXB或JAX-WS。 描述中提到,将解压后的jar包放置在`%TOMCAT_HOME%`和`%JAVA_HOME%\lib\endorsed`...

    JBoss管理与开发

    ### JBoss管理与开发之JBoss JMX实现架构详解 #### 一、引言 JBoss作为一款流行的开源应用服务器,提供了丰富的功能和支持多种企业级应用程序的部署与管理。JBoss JMX(Java Management Extensions)实现架构是...

    juel-impl.jar

    javax.servlet.ServletException: java.lang.LinkageError

    CXF-JAXB包的处理问题

    而JAXB(Java Architecture for XML Binding)是Java平台的标准,用于将XML数据与Java对象之间进行绑定,使得开发者可以方便地在XML文档和Java对象之间转换。在处理CXF与JAXB的集成时,有时会遇到版本冲突的问题,...

Global site tag (gtag.js) - Google Analytics