类加载器的相关问题(ClassLoader&&LinkageError)

原创 2004年12月29日 15:30:00

下面的错误在google上搜了半天也没有特别满意的答案,后来看到一篇关于JUnit类加载器Bug的文章,总算觉得柳暗花明....
  

java.lang.LinkageError: Class org/w3c/dom/Document violates loader constraints at
java.lang.ClassLoader.defineClass0(Native Method) at
java.lang.ClassLoader.defineClass(ClassLoader.java:502) at
java.lang.ClassLoader.defineClass(ClassLoader.java:431) at
.......

这样的异常,主要是由于非系统 类加载器,即自定义的类加载器出现了问题,这个类加载器试图加载org.w3c.dom.Document ,此时如果类加载器没有进行正确的处理,或者Document 类不在JVM's system classpath下,类加载器便无法加载,自己加载不了,也不通知系统类加载器,上面的错误就出现啦。。。

可能理解有问题,可参照下面这篇文章,我试验了一下,完全可信:


Here's a patch for JUnit's busted classloader: junit-patch.jar.  And below is XmlTest.java, a regression test that breaks (with a java.lang.LinkageError) with the old classloader and the swingui/awtui TestRunners, but passes with the patch.

junit-patch.jar contains two classes (source included):

  1. ReloadableTestClassLoader - a properly delegating custom ClassLoader that currently relies on a System property value for its classpath: junit.test.path. The fix can be ported to junit.runner.TestCaseClassLoader or it can be effected through a new ClassLoader like this one.
  2. ReloadingTestSuiteLoader - modified to return this custom ClassLoader. If I can get this fix applied to the real JUnit, this class wouldn't necessarily need to be modified (it's only like 5 lines) because we could fix the original TestCaseClassLoader instead of writing a new one. Whatever; minor detail.

XmlTest.java:

import junit.framework.TestCase;
import javax.xml.parsers.*;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
    
public class XmlTest extends TestCase {

Document doc = null; public void testXml() throws ParserConfigurationException { doc = DocumentBuilderFactory.newInstance() .newDocumentBuilder() .newDocument(); // System.out.println("Hello! I changed again"); Element root = doc.createElement("xml-test"); assertNotNull(root); } }

This is a simple test that reproduces a LinkageError with the JUnit buggy ClassLoader under the following conditions:

  1. Use Sun JDK 1.4.x
  2. Edit JUnit's excluded.properties so that you comment out the exclusion of org.w3c.dom.* -- this is necessary to reveal the bug and is the easiest test I could think of. Make sure your edited excluded.properties is first in the classpath or updated into junit.jar at junit/runner/excluded.properties (BTW, obviously the new ReloadableTestClassLoader doesn't use or rely on excluded.properties at all).
  3. Put the DOM interfaces (in Xerces these are in xml-apis.jar) and an XML parser impl, such as Xerces, in your classpath to reproduce the bug. Why? Since you will have unexcluded org.w3c.dom.* in excluded.properties, JUnit will attempt to load those interfaces rather than delegate to the system loader. But they aren't in the scope of JUnit's buggy classloader if they aren't in the JVM's system classpath, so you have to add them. I.e., the 1.4.x JVM loads these in its boot loader, whose classpath JUnit's buggy loader doesn't know about.
  4. Example of command line to use to reproduce the bug (using junit.jar from JUnit 3.8.1, but any version should work): java -cp .;junit.jar;xml-apis.jar;xerces.jar junit.swingui.TestRunner XmlTest

You should see this in the runner's error display window:

 java.lang.LinkageError: Class org/w3c/dom/Document violates loader constraints at
java.lang.ClassLoader.defineClass0(Native Method) at 
java.lang.ClassLoader.defineClass(ClassLoader.java:502) at 
java.lang.ClassLoader.defineClass(ClassLoader.java:431) at 
junit.runner.TestCaseClassLoader.loadClass(TestCaseClassLoader.java:104) at 
java.lang.ClassLoader.loadClass(ClassLoader.java:255) at 
java.lang.ClassLoader.loadClassInternal(ClassLoader.java:315) at 
XmlTest.testXml(XmlTest.java:16) 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:324) at 
junit.framework.TestCase.runTest(TestCase.java:154) at 
junit.framework.TestCase.runBare(TestCase.java:127) at 
junit.framework.TestResult$1.protect(TestResult.java:106) at 
junit.framework.TestResult.runProtected(TestResult.java:124) at 
junit.framework.TestResult.run(TestResult.java:109) at 
junit.framework.TestCase.run(TestCase.java:118) at 
junit.framework.TestSuite.runTest(TestSuite.java:208) at 
junit.framework.TestSuite.run(TestSuite.java:203) at 
junit.swingui.TestRunner$16.run(TestRunner.java:623)

Now run the same test with the fixed ClassLoader:

  1. shadow classes in junit.jar by listing junit-patch.jar first in the classpath
  2. set junit.test.path property to include the path to XmlTest.class
  3. run XmlTest with the Swing or AWT test runner:
    java -cp junit-patch.jar;junit.jar -Djunit.test.path=. junit.swingui.TestRunner XmlTest

ClassLoader类加载器

  • 2016年04月13日 18:03
  • 22KB
  • 下载

java面试之ClassLoader类加载器

1.1、概念 类加载器(class loader)用来加载 Java 类到 Java 虚拟机中。一般来说,Java虚拟机使用 Java 类的方式如下:Java 源程序(.java 文件)在经过 Ja...
  • stypace
  • stypace
  • 2014年10月30日 08:40
  • 2118

一个自定义类加载器ClassLoader示例

我们的自定义类加载器

深入理解Java类加载器(ClassLoader)

【版权申明】未经博主同意,谢绝转载!(请尊重原创,博主保留追究权) http://blog.csdn.net/javazejian/article/details/73413292 出自【zeji...

Java 类加载器Classloader机制解析

转载自:点击打开链接 做Java开发,对于ClassLoader的机制是必须要熟悉的基础知识,本文针对Java ClassLoader的机制做一个简要的总结。因为不同的JVM的实现不同,本文所描述的...

深入理解java类加载器ClassLoader

类加载器(class loader)用来加载 Java 类到 Java 虚拟机中。一般来说,Java 虚拟机使用 Java 类的方式如下:Java 源程序(.java 文件)在经过 Java 编译...
  • zcxwww
  • zcxwww
  • 2016年05月02日 18:31
  • 411

Java类加载器ClassLoader的说明

(1)API文档内容如下:类加载器是负责加载类的对象。ClassLoader 类是一个抽象类。如果给定类的二进制名称,那么类加载器会试图查找或生成构成类定义的数据。一般策略是将名称转换为某个文件名,然...

java 类加载器ClassLoader详解(一)——原理与模式

一 、ClassLoader的体系结构 (1).启动类加载器(Bootstrap ClassLoader):他是由C++编写而成,并且已经内嵌到JVM中,负责将$JRE_HOME\lib目录中的,或者...
  • lxxc11
  • lxxc11
  • 2015年11月16日 14:59
  • 278

理解java类加载器以及ClassLoader类

类加载器概述:   java类的加载是由虚拟机来完成的,虚拟机把描述类的Class文件加载到内存,并对数据进行校验,解析和初始化,最终形成能被java虚拟机直接使用的java类型,这就是虚拟机的...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:类加载器的相关问题(ClassLoader&&LinkageError)
举报原因:
原因补充:

(最多只允许输入30个字)