`
deepnighttwo
  • 浏览: 49820 次
  • 性别: 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

    el-api.jar

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

    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-...

    Burpsuite永久版

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

    juel-impl.jar

    javax.servlet.ServletException: java.lang.LinkageError

    jaxb-2_1_9.zip

    java.lang.LinkageError: JAXB 2.0 API is being loaded from the bootstrap classloader, but this RI (from jar:file://build/web/WEB-INF/lib/jaxb-impl.jar!/com/sun/xml/bind/v2/model/impl/ModelBuilder.class...

    SOFAArk 是一款基于 Java 实现的动态热部署和轻量级类隔离框架.rar

    日常使用 Java 开发,常常会遇到包依赖冲突的问题,尤其当工程应用变得臃肿庞大,包冲突的问题也会变得更加棘手,导致各种各样的报错,例如LinkageError, NoSuchMethodError等;实际开发中,可以采用多种方法来解决...

    SOFAArk Project Java轻量级类隔离框架 v2.1.3

    SOFAArk 最初的场景是解决 Java 开发常常会遇到的包依赖冲突的问题,尤其当工程应用变得臃肿庞大,包冲突的问题也会变得更加棘手,导致各种各样的报错,例如LinkageError, NoSuchMethodError等。实际开发中,可以...

    java 异常总结

    其他还有很多异常,我就不一一列举了,我要说明的是,一个合格的程序员,需要对程序中常见的问题有相当的了解和...假设有类A和B(A不是B的父类或子类),O是A的实例,那么当强制将O构造为类B的实例时抛出该异常。该异常

    mima:一种在Scala中捕获二进制不兼容的工具

    MiMa可以报告二进制修改,这些修改可能导致JVM在运行时抛出java.lang.LinkageError (或其子类型之一,例如AbstractMethodError )。 链接错误通常是类/成员签名修改的结果。 MiMa比较了两个已发布库的所有类文件,...

    sofa-ark:SOFAArk是一个轻量级的,基于Java的类加载器隔离框架

    背景日常使用 Java 开发,常常会遇到包依赖冲突的问题,尤其当工程应用变得臃肿庞大,包冲突的问题也会变得更加棘手,导致各种各样的报错,例如LinkageError, NoSuchMethodError等;实际开发中,可以采用多种方法来...

    endorsed 解决soa连接错误

    下载本包解压后放在%TOMCAT_HOME%和%JAVA_HOME%\lib下(jar包必须在endorsed 文件夹下)

Global site tag (gtag.js) - Google Analytics