类加载器的相关问题(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)

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

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

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

Java类加载器classLoader的工作机制

类加载器就是寻找类或接口字节码文件进行解析并构造JVM内部对象表示的组件。在文章中介绍了类装载器的步骤和分类情况。

java反射Reflection(一)之的类加载器ClassLoader和Class类

反射就是把Java的各种成分映射成相应的Java类。      反射是java语言的一个特性,它允程序在运行时(注意不是编译的时候)来进行自我检查并且对内部的成员进行操作。例如它允许一个java的...

java笔记--理解java类加载器以及ClassLoader类

类加载器概述:   java类的加载是由虚拟机来完成的,虚拟机把描述类的Class文件加载到内存,并对数据进行校验,解析和初始化,最终形成能被java虚拟机直接使用的java类型,这就是虚拟机的类加载...

深入理解java类加载器ClassLoader

类加载器(class loader)用来加载 Java 类到 Java 虚拟机中。一般来说,Java 虚拟机使用 Java 类的方式如下:Java 源程序(.java 文件)在经过 Java 编译...

理解java类加载器以及ClassLoader类

类加载器概述:   java类的加载是由虚拟机来完成的,虚拟机把描述类的Class文件加载到内存,并对数据进行校验,解析和初始化,最终形成能被java虚拟机直接使用的java类型,这就是虚拟机的...

Java虚拟机(六):类加载器ClassLoader

“通过一个类的全限定名来获取描述此类的二进制流”这个动作放到虚拟机外部去实现,以便让应用程序决定如何去获取所需要的类。这个动作模块就是类加载器。而程序在启动的时候,并不会一次性加载程序所要用的所有cl...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

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