`
AquariusM
  • 浏览: 146839 次
  • 性别: Icon_minigender_1
  • 来自: 南阳
社区版块
存档分类
最新评论

关于类加载时LinkageError的问题记录

 
阅读更多

今天遇到一个比较奇怪的问题,MultiPageEditor所使用的类和子Page使用了同一个类,因为我使用的是同一个jar包里的类,两个工程各自使用自己的jar包,但是是一个相同的jar包,这样在运行时,就出现了这个错误:

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

a different type with name “"

链接过来一个问题说明:

一下内容转载自:

 (转载请说明)

http://www.cnblogs.com/deepnighttwo/archive/2011/08/31/2160990.html

 

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的规则。

 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程序:

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

 

分享到:
评论

相关推荐

    classloader类加载器_基于java类的加载方式详解

    如果尝试使用同一个类加载器再次加载同一个类,将会抛出java.lang.LinkageError异常,异常信息为duplicate class definition。要更新一个类,只能创建一个新的类加载器实例来加载新类。对于已经被加载的类,开发者不...

    类的加载机制笔记

    它不仅有助于我们更好地理解Java程序是如何运行的,还可以帮助我们在实际开发中解决很多问题,比如类加载失败导致的`LinkageError`异常等。因此,在学习过程中,我们应该注重对原理的理解,而不仅仅是掌握操作方法。

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

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

    jvm系列(一)java类地加载机制.doc

    JVM 规定允许类加载器在预料某个类将要被使用时就预先加载它,如果在预先加载的过程中遇到了.class 文件缺失或存在错误,类加载器必须在程序首次主动使用该类时才报告错误(LinkageError 错误)。如果这个类一直没有...

    Burpsuite永久版

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

    CXF-JAXB包的处理问题

    首先,LinkageError通常发生在类加载过程中,当试图访问的类在不同的类加载器中具有不兼容的实现时。在这种情况下,错误消息指出,JAXB 2.1 API正在由引导类加载器加载,但实际的实现需要2.2 API。这可能是由于系统...

    JBoss JMX实现架构

    - LinkageError:在类加载期间或之后出现的链接错误,通常发生在引用的类或接口在运行时不可用或不匹配的情况下。这可能源于类加载器的不正确使用,导致了类版本冲突。 - IllegalAccessError:当尝试访问私有方法或...

    北京圣思园深入Java虚拟机

    - 虽然JVM规范允许类加载器在预料某个类将要被使用时就预先加载它,但如果在这个过程中遇到`.class`文件缺失或存在错误,则类加载器必须在程序首次主动使用该类时才报告错误(例如`LinkageError`)。 5. **类的...

    jmx资料

    `ClassCastException`、`LinkageError`和`IllegalAccessError`等异常可能在静态编译时不易察觉,但在运行时动态加载类时可能出现。例如,不同`URLClassLoader`加载的相同jar文件会被视为不同的类,导致`...

    Burp suite主题插件.jar

    当他们这样做时,黑客们到处欢欣鼓舞!但是,有些人仍然想要更多......直到...... Burp Customizer! Burp Suite 2020.12 用 FlatLaf 替换了旧的 Look and Feel 类,这是一个开源 Look and Feel 类,它还支持为 ...

    关于java热部署知识.doc

    当一个类需要加载时,它会首先尝试由父ClassLoader加载,只有当父ClassLoader无法找到该类时,才会由当前ClassLoader加载。这种机制防止了类的冲突,并确保了系统类如`String`只能由JRE的ClassLoader加载。 在JVM中...

    异常的分类以及处理方法

    例如,当遇到`LinkageError`、`ThreadDeath`等系统级别的错误时,通常意味着程序出现了严重的运行时错误,此时应考虑记录错误日志、进行异常信息的打印等操作,而不是尝试恢复执行。 示例代码: ```java try { // ...

    endorsed 解决soa连接错误

    `java.lang.LinkageError`是一个运行时异常,通常在类加载期间或之后出现,当一个类依赖的另一个类存在不兼容的情况时抛出。这里的“nested exception”意味着错误可能源于另一个更深层次的异常,可能是由于使用了不...

    Java常见异常.pdf

    23. **LinkageError**:链接错误,涉及类加载时的依赖问题,如类定义改变。 24. **NoClassDefFoundError**:未找到类定义错误,当类加载时找不到对应的类定义。 25. **NoSuchFieldError**:域不存在错误,当尝试...

    JAVA异常分类.txt

    - **LinkageError**:与类加载相关的错误。 - **NoClassDefFoundError**:在类初始化时找不到类的定义。 - **VerifyError**:类文件验证失败。 ### 其他异常 还有一些特定于某些功能或上下文的异常: - **...

    JBoss管理与开发

    `java.lang.IllegalAccessError`异常表示某个类试图访问另一个类的私有成员(字段或方法)时出现了权限问题。这通常发生在不同类装载器装载的类试图相互访问对方的私有成员时。 #### 五、结论 通过对JBoss JMX实现...

    Java中常见的异常分析

    23. **链接错误:LinkageError** - 类的依赖关系发生变化导致的错误,如类加载器问题。 24. **未找到类定义错误:NoClassDefFoundError** - Java虚拟机找不到类定义时抛出。 25. **域不存在错误:NoSuchFieldError...

    常见JAVA异常总结

    通常发生在使用反射机制动态加载类时,如果类路径中找不到指定的类,则会抛出此异常。 - **原因**:类路径设置错误,或者依赖的 jar 包未被正确添加到项目中。 - **解决方法**: - 检查类路径(classpath),确保...

    java异常汇总.txt

    当类加载器找不到某个类的定义时,会抛出`NoClassDefFoundError`。这可能由类路径配置错误或依赖库缺失引起。 #### 25. NoSuchFieldError - 字段未找到错误 当反射API尝试访问不存在的字段时,会抛出`...

Global site tag (gtag.js) - Google Analytics