首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >NoClassDefFoundError: org/w3c/dom/ls/DocumentLS -只有在编译时将其修复后才会在部署中发生问题

NoClassDefFoundError: org/w3c/dom/ls/DocumentLS -只有在编译时将其修复后才会在部署中发生问题
EN

Stack Overflow用户
提问于 2020-05-25 16:03:36
回答 1查看 12.2K关注 0票数 9

背景

我有一个解析一些XML文档的项目,我碰巧需要xerces依赖:

代码语言:javascript
运行
复制
<dependency>
    <groupId>xerces</groupId>
    <artifactId>xerces</artifactId>
    <version>2.4.0</version>
</dependency>

在用junit4编写单元测试时,每次运行单元测试时都会遇到问题,每次使用mvn clean install编译时都会发生以下情况

代码语言:javascript
运行
复制
[ERROR] Tests run: 1, Failures: 0, Errors: 1, Skipped: 0, Time elapsed: 0.346 s <<< FAILURE! - in ConversionTest
[ERROR] ConversionTest.initializationError  Time elapsed: 0.054 s  <<< ERROR!
java.lang.NoClassDefFoundError: org/w3c/dom/ls/DocumentLS
        at ConversionTest.fromDirectory(ConversionTest.java:92)
        at ConversionTest.data(ConversionTest.java:65)
Caused by: java.lang.ClassNotFoundException: org.w3c.dom.ls.DocumentLS
        at ConversionTest.fromDirectory(ConversionTest.java:92)
        at ConversionTest.data(ConversionTest.java:65)

编译时解决方案

搜索web时,我意识到我需要在我的pom.xml中添加一个新的依赖项:

代码语言:javascript
运行
复制
<dependency>
    <groupId>xerces</groupId>
    <artifactId>xercesImpl</artifactId>
    <version>2.11.0</version>
</dependency>

在这样做之后,测试编译得很好,我可以生成我的.jar,它是用以下内置插件打包的:

代码语言:javascript
运行
复制
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-jar-plugin</artifactId>
            <version>2.4</version>
            <configuration>
                <archive>
                    <manifest>
                        <addClasspath>true</addClasspath>
                        <classpathPrefix>lib/</classpathPrefix>
                        <mainClass>com.company.tools.Application</mainClass>
                    </manifest>
                </archive>
            </configuration>
        </plugin> 

..。并使用下列设置进行编译:

代码语言:javascript
运行
复制
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>${maven.compiler.plugin.version}</version>
            <configuration>
                <encoding>cp1252</encoding>
                <release>11</release>
                <fork>true</fork>
                <meminitial>128m</meminitial>
                <maxmem>512m</maxmem>
                <compilerArgs>
                    <arg>-Xpkginfo:always</arg>
                </compilerArgs>
            </configuration>
        </plugin>

这产生了一个包含所有所需依赖项的.jar,这里包括著名的org/w3c/dom/ls/DocumentLS

部署

现在,我将这个.jar移动到我的服务器中,并尝试使用以下命令运行它:

代码语言:javascript
运行
复制
java -jar myJar.jar <inputs>

当我这样做,我得到以下例外,再次!

代码语言:javascript
运行
复制
Exception in thread "main" java.lang.NoClassDefFoundError: org/w3c/dom/ls/DocumentLS
        at java.base/java.lang.ClassLoader.defineClass1(Native Method)
        at java.base/java.lang.ClassLoader.defineClass(ClassLoader.java:1016)
        at java.base/java.security.SecureClassLoader.defineClass(SecureClassLoader.java:174)
        at java.base/jdk.internal.loader.BuiltinClassLoader.defineClass(BuiltinClassLoader.java:801)
        at java.base/jdk.internal.loader.BuiltinClassLoader.findClassOnClassPathOrNull(BuiltinClassLoader.java:699)
        at java.base/jdk.internal.loader.BuiltinClassLoader.loadClassOrNull(BuiltinClassLoader.java:622)
        at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:580)
        at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178)
        at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:521)
        at org.apache.xerces.jaxp.DocumentBuilderImpl.<init>(Unknown Source)
        at org.apache.xerces.jaxp.DocumentBuilderFactoryImpl.newDocumentBuilder(Unknown Source)
        at com.company.tools.impl.FileProviderImpl.getXmlFile(FileProviderImpl.java:68)
        at com.company.tools.impl.FileProviderImpl.<init>(FileProviderImpl.java:38)
        at com.company.tools.impl.FileProviderImpl$Builder.build(FileProviderImpl.java:91)
        at com.company.tools.Application.main(Application.java:50)
Caused by: java.lang.ClassNotFoundException: org.w3c.dom.ls.DocumentLS
        at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:582)
        at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178)
        at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:521)
        ... 15 more

我的问题和关于机器的一些细节

我在这里有点迷路了。我已经将依赖项添加到我的pom.xml中,类在.jar中打包得很好,但我仍然有同样的问题。我做错了什么?

如果可以的话:

我的机器

代码语言:javascript
运行
复制
Java version: 11.0.2-BellSoft, vendor: BellSoft, runtime: C:\jdk-11.0.2
Default locale: fr_FR, platform encoding: Cp1252
OS name: "windows 10", version: "10.0", arch: "amd64", family: "windows"

我的服务器

代码语言:javascript
运行
复制
openjdk version "11" 2018-09-25
OpenJDK Runtime Environment 18.9 (build 11+28)
OpenJDK 64-Bit Server VM 18.9 (build 11+28, mixed mode)
OS: Linux myServerAddress 3.10.0-327.el7.x86_64 #1 SMP Thu Oct 29 17:29:29 EDT 2015 x86_64 x86_64 x86_64 GNU/Linux

提前感谢!

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-05-28 13:02:03

由于@Sambit第二条关于这个GitHub问题的评论,我最终找到了解决方案。张贴在这里的答案,希望它可以挽救其他人的头痛天!

基本上,我在我的pom.xml里有这个

代码语言:javascript
运行
复制
<dependencies>
    <dependency>
        <groupId>xerces</groupId>
        <artifactId>xerces</artifactId>
        <version>2.4.0</version>
    </dependency>
    <dependency>
        <groupId>xerces</groupId>
        <artifactId>xercesImpl</artifactId>
        <version>2.11.0</version>
    </dependency>
</dependencies>

在这两种情况下(单元测试和主代码),此代码都会引发异常:

代码语言:javascript
运行
复制
try(InputStream is = new FileInputStream(file)) {
    documents.put(file.getName(), DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(is));
}

..。特别是,通过对newDocumentBuilder()的调用,它正在寻找DocumentImpl类型的实现。

问题解释

第一个依赖项xerces是在不推荐的xercesImpl版本上提取一个传递依赖项。因此,当我运行测试时,代码正在编译(因为依赖项在那里),但是当newDocumentBuilder()在寻找DocumentImpl时,错误的依赖项返回了该实现,该依赖项正在寻找没有成功的org/w3c/dom/ls/DocumentLS,因此引发了NoClassDefFoundError

一旦我在pom中将显式依赖添加到xercesImpl中,junit运行程序就会明白,与其在不推荐的xercesImpl版本中搜索DocumentImpl,不如在显式依赖中查找它,从而解决问题。

但是,在服务器上运行程序的JVM没有采用相同的假设:newDocumentBuilder()仍然在传递依赖项中寻找DocumentImpl,所以问题仍然存在。

分辨率

消除传递依赖关系:

代码语言:javascript
运行
复制
<dependencies>
    <dependency>
        <groupId>xerces</groupId>
        <artifactId>xerces</artifactId>
        <version>2.4.0</version>
        <exclusions>
            <exclusion>
                <groupId>xerces</groupId>
                <artifactId>xercesImpl</artifactId>
            <exclusion>
        </exclusions>
    </dependency>
    <dependency>
        <groupId>xerces</groupId>
        <artifactId>xercesImpl</artifactId>
        <version>2.11.0</version>
    </dependency>
</dependencies>    
票数 11
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/62006284

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档