当前位置: 首页 > 面试题库 >

使用Gradle在运行时出现NoClassDefFoundError

桓宜
2023-03-14
问题内容

我正在使用gradle作为JavaFX插件。即使在 distribution /下
构建和运行可执行文件之后,一切都可以完美运行,但只有一类:CloseableHttpClient

为了多种目的,我创建了以下对象:

CloseableHttpClient client = HttpClients.createDefault();

在IDE中运行该程序没问题,一切正常。但是,如果我构建并尝试运行.exe文件,Throwable则会得到以下-StackTrace:

java.lang.NoClassDefFoundError: Could not initialize class org.apache.http.conn.ssl.SSLConnectionSocketFactory
    at org.apache.http.impl.client.HttpClientBuilder.build(HttpClientBuilder.java:955)
    at org.apache.http.impl.client.HttpClients.createDefault(HttpClients.java:58)
    at ch.itcb.tools.lom.util.JsonSimpleUtil.http(JsonSimpleUtil.java:29)...

我真的不明白。怎么可能找不到这个类,而我所有其他的类却都找不到呢?

我的build.gradle文件:

apply plugin: 'java'
apply plugin: 'eclipse'
apply from: 'javafx.plugin'

sourceCompatibility = 1.8
version = '0.1'

jar {
    manifest {
        attributes 'Implementation-Title': 'LogoffManager',
                   'Implementation-Version': version
    }
}

repositories {
    mavenCentral()
}

dependencies {
    compile fileTree(dir: 'lib', include: ['*.jar'])

    compile 'ch.qos.logback:logback-classic:1.1.3'

    compile 'org.apache.httpcomponents:httpclient:4.5.1'

    compile 'com.googlecode.json-simple:json-simple:1.1'



    compile group: 'commons-collections', name: 'commons-collections', version: '3.2'
    testCompile group: 'junit', name: 'junit', version: '4.+'
}

test {
    systemProperties 'property': 'value'
}

uploadArchives {
    repositories {
       flatDir {
           dirs 'repos'
       }
    }
}

如果您需要更多信息,请发表评论。谢谢。


问题答案:

这是一个很好的问题,我在研究Java开发人员可以通过类路径乐趣最终获得许多方法的示例时遇到了:-)

我从build.gradle的最低版本开始(仅包括直接相关的版本),特别是:

plugins {
    id 'java'
}
sourceCompatibility = 1.8

repositories {
    mavenCentral()
}

jar {
    manifest {
        attributes 'Main-Class': 'com.oliverlockwood.Main'
    }
}

dependencies {
    compile 'org.apache.httpcomponents:httpclient:4.5.1'
}

在这种情况下,我的“ Main”类使用您的代码示例,即:

package com.oliverlockwood;

import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;

public class Main {
    public static void main(String[] args) {
        CloseableHttpClient client = HttpClients.createDefault();
    }
}

在此阶段,我可以gradle clean build依次运行java -jar build/libs/33106520.jar(我的项目以该StackOverflow问题命名),然后看到:

Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/http/impl/client/HttpClients
    at com.oliverlockwood.Main.main(Main.java:8)
Caused by: java.lang.ClassNotFoundException: org.apache.http.impl.client.HttpClients
    at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:357)

这与您的错误有细微的差别,但是在我们进行挖掘和重现之前,请让我强调一下:该错误和您看到的错误都是在运行时在类加载器找不到所需的类时引起的。有相当不错的博客文章在这里约编译时类路径和运行时类路径之间的区别的更多细节。

如果运行gradle dependencies,则可以看到项目的运行时依赖项:

runtime - Runtime classpath for source set 'main'.
\--- org.apache.httpcomponents:httpclient:4.5.1
     +--- org.apache.httpcomponents:httpcore:4.4.3
     +--- commons-logging:commons-logging:1.2
     \--- commons-codec:commons-codec:1.9

我将这些手动一一添加到我的运行时类路径中。(记录下来,这通常不被认为是一种好习惯;但是为了进行实验,我将这些罐子复制到了我的build/libs文件夹中并使用来运行java -cp build/libs/33106520.jar:build/libs/* com.oliverlockwood.Main。有趣的是,这无法重现您的确切问题。

  • 如果org.apache.httpcomponents:httpclient在运行时不可用,那么我们将失败,因为HttpClients找不到该jar。
  • 由于org.apache.httpcomponents:httpclient:4.5.1运行时可用,因此您的问题就不会显现-我注意到您的构建未能找到的类(org.apache.http.conn.ssl.SSLConnectionSocketFactory)是 该同一个Apache库的一部分,这 确实非常可疑。

然后,我怀疑您的运行时类路径包含Apache httpclient库的 不同版本
。由于那里有很多lotta版本,因此我不会测试每种组合,因此我将为您提供以下建议。

  1. 如果您想完全了解问题的根本原因,请 准确 确定错误情况下运行时类路径中存在哪些jar(包括其版本),包括创建胖jar时打包在您的jar中的所有jar(在第3点中对此有更多的了解。如果您在此处共享这些详细信息,那就太好了;根本原因分析通常可以帮助所有人更好地理解:-)
  2. 尽可能避免以方式使用依赖项compile fileTree(dir: 'lib', include: ['*.jar'])。与诸如随机目录中的依赖关系相比,基于Maven或JCenter之类的存储库的托管依赖关系更易于一致地使用。如果您不想将这些内部库发布到开源工件存储库中,那么可能值得设置本地Nexus实例或类似实例。
  3. 考虑生产“胖罐子”而不是“薄罐子”-这意味着所有运行时依赖项都打包在您构建的罐子中。我建议为Gradle提供一个很好的Shadow插件 -将其放置在我的build.gradle,然后运行gradle clean shadow,我可以java -jar很好地运行,而无需手动将任何东西添加到我的类路径中。


 类似资料:
  • 我正在尝试使用GPU而不是CPU运行dl4j模型。该模型使用CPU运行良好。所以我决定尝试CUDA来利用我的GPU。我遵循了这里描述的每个步骤,对于CUDA安装,我按照NVIDIA的说明从这里安装CUDA工具包。代码编译正常,但出现错误: 我的项目是使用IntelliJ上的Maven创建的。所有的依赖项都是可以的,否则代码将无法编译。必须缺少某些后端依赖项、库或安装。可能是版本不兼容的问题 消息为

  • 问题内容: 我需要在Flask应用程序上定期运行某些任务。我决定使用一个简单的库-Schedule(https://github.com/dbader/schedule)来执行此操作。我在与主应用程序线程不同的线程上运行任务计划程序。这是相关的代码片段。 运行此程序时,我想要“运行定期任务!” 每10秒打印一次。但是,这是我得到的输出。 显然,由于某种原因,任务似乎每10秒执行两次,而不是一次。但

  • 现在,当我运行和时,一切都很好,但是当我尝试运行项目时(在build/libs/中运行构建的jar和在IntelliJ中运行velotest类时也是如此),我会得到以下错误: 线程“main”java.lang.noClassDefFounderror:org/apache/commons/collections/extendedProperties 在org.apache.velocity.ru

  • 在我的计算机上升级Gradle安装后,当以VS代码打开现有的Gradle项目时,我开始收到以下错误消息: 无法使用分级分发“https://services.Gradle.org/distributions/gradle-5.5.1-bin.zip”运行生成操作)。 我发现类似的问题随着不同的版本号四处飘荡,例如:无法使用Gradle发行版'https://services.Gradle.org/

  • 我使用Gradle构建了一个jar文件。它在“Gradle Run”中运行得很好,但是当我在Eclipse中运行它时(运行->外部工具->外部工具配置),我在一个Spring类上得到了NoClassDefoundError。 这是大楼。格雷德尔: 我查看了jar文件,它没有依赖的jar,这就是为什么在Eclipse中运行时出现NoClassDefinition错误的原因。我也尝试过在本地包含这些J