Maven中依赖包为provided导致的java.lang.NoClassDefFoundError解决

简介
        最近从eclipse转到IDEA,一开始就遇到问题,以前eclipse运行的MAVEN管理的程序,在IDEA中,总要报错NoClassDefFoundError比如:
Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/spark/api/java/function/Function2
    at java.lang.Class.forName0(Native Method)
    at java.lang.Class.forName(Class.java:264)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:122)
Caused by: java.lang.ClassNotFoundException: org.apache.spark.api.java.function.Function2
    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)
    ... 3 more
       
问题解析
         一时间相当郁闷,明明都引入了包了,在eclipse中都能运行,在IDEA中为何不行。一番研究后终于发现问题所在出现于此:
        在我的pom文件中是这样的:

<dependency>
   <groupId>org.apache.spark</groupId>
   <artifactId>spark-core_2.10</artifactId>
   <version>2.1.0</version>
   <scope>provided</scope>
</dependency>
        这在eclipse中完全没问题,但是在IDEA中,maven配置<scope>provided</scope>,依赖只作用于编译和打包等,但不能用于运行类。通俗的说,配置了<scope>provided</scope>,就是在告诉IDEA,你不要担心,我会在运行时提供这个依赖,但是实际上却并没有提供依赖。除非将这个依赖加到类路径下,那么就OK了。所以解决办法也就出来了.

解决办法
        1.保留<scope>provided</scope>配置项,然后手动将依赖加到类路径。
                       如何添加依赖参看http://blog.csdn.net/a153375250/article/details/50851049
                       或者这样也行:File–>Project Structure–>左侧 Libraries,中间新建一个 lib 的project Library,选择 Java,然后在选择项目中的 jar 所在的文件夹

            2.去掉<scope>provided</scope>,改为<scope>compile</scope>,当然只去掉也可,默认就是compile。注:改完后,在maven上运行一下reimport,重新导入一下。打完收工。

### Maven 编译后出现 `java.lang.NoClassDefFoundError` 的解决方案 #### 问题分析 `java.lang.NoClassDefFoundError` 是一种常见的 Java 运行异常,通常表示 JVM 在运行期间无法找到某个类的定义。这种错误可能由多种原因引起,例如依赖项缺失、classpath 配置不正确或打包过程中未包含必要的库文件。 对于基于 Maven 构建的应用程序来说,该问题通常是由于以下原因之一造成的: - **缺少依赖**:某些第三方库在编译阶段可用但在运行不可用。 - **作用域配置不当**:Maven 中的 `<scope>` 设置可能导致某些依赖仅限于特定环境(如测试),而不在最终构建产物中。 - **打包方式错误**:如果项目被打包成 JAR 文件,则需要确保所有依赖都被正确嵌入到可执行 JAR 中。 --- #### 解决方案 ##### 方法一:检查并修复 POM.xml 中的依赖范围 确认项目的 `pom.xml` 是否存在不必要的 `<scope>` 标签设置。默认情况下,Maven 将依赖的作用域设为 `compile`,这意味着这些依赖会在编译和运行都可用。然而,如果设置了其他作用域(如 `provided` 或 `test`),则可能导致运行找不到对应的类。 以下是常见作用域及其含义: - `compile`:适用于大多数场景,默认值。 - `runtime`:只在运行加载,不会参与编译。 - `test`:仅用于单元测试。 - `provided`:假设目标环境中已提供此依赖(如 Servlet 容器中的 API)[^2]。 修正示例: ```xml <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> <version>3.9</version> <!-- 如果有 scope,请移除或者改为 compile --> <!--<scope>provided</scope>--> </dependency> ``` ##### 方法二:使用 Shade 插件创建 Fat Jar 为了确保所有的依赖都能被包含在一个单独的 JAR 文件中,可以利用 Maven Shade Plugin 来生成所谓的“Fat Jar”。这种方式会将所有依赖复制到主 JAR 文件内部,从而避免因 classpath 不完整而导致的 `NoClassDefFoundError` 错误。 配置示例: ```xml <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-shade-plugin</artifactId> <version>3.2.4</version> <executions> <execution> <phase>package</phase> <goals> <goal>shade</goal> </goals> <configuration> <transformers> <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer"> <mainClass>com.example.MainApp</mainClass> </transformer> </transformers> </configuration> </execution> </executions> </plugin> </plugins> </build> ``` 通过上述插件,可以在运行 `mvn package` 命令后得到一个完整的 JAR 文件,其中包含了所有所需的依赖项[^1]。 ##### 方法三:验证 ClassLoader 加载路径 有即使依赖已经存在于本地仓库中,也可能因为动态加载机制未能成功解析所需资源。此可以通过打印当前线程上下文中使用的类加载器来排查具体问题所在: 调试代码如下所示: ```java public static void main(String[] args) { System.out.println("Thread ContextClassLoader: " + Thread.currentThread().getContextClassLoader()); } ``` 此外还可以尝试手动指定启动参数 `-Djava.class.path=...` 明确告知 JVM 所需查找的位置[^3]。 --- ### 总结 针对 Maven 工程中发生的 `java.lang.NoClassDefFoundError` ,应优先审查是否存在遗漏的关键外部组件;其次调整合适的依赖管理策略比如借助 shade plugin 实现自给自足型 jar 输出形式;最后必要候深入探究底层实现细节以便定位根本诱因。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值