MAVEN使用的一些tips

java.lang.NoClassDefFoundError

现象

JAVA中的NoClassDefFoundError错误表示一个类在编译时通过,但在运行时找不到。有一种场景是,我们用IDE编写一些业务功能,然后将它打成jar包放到某个集群中运行,比如hadoop,storm等。

解释

因为编译的环境是在本地的IDE,而运行的环境是在某个集群环境,可能出现因为本地编译环境存在某个依赖,集群中不存在这个依赖,因为maven默认编译时不会将lib打到jar包中,所以运行环境就找不到这个依赖,报出NoClassDefFoundError的错误。

解决

  • 既然是缺少依赖,那解决方案就是把依赖添加进去。怎么添加呢,这里介绍两种方法。
  1. 找到运行时缺少的依赖,添加到集群(运行环境)的lib中。通常地,在IDE中定位到缺少的类对应的jar包,然后到本地maven仓库中将jar包找出来,放到集群公共的lib目录下即可。
  2. 在maven打包时,将需要的lib包和源码一起打成jar包,这样运行时缺少依赖的问题就解决啦。首先在pom.xml中添加如下plugin:
<build>
	<plugins> 
            <plugin>  
                <artifactId>maven-assembly-plugin</artifactId>  
                <configuration>  
                    <archive>  
                        <manifest>  
                            <mainClass>com.allen.capturewebdata.Main</mainClass>  
                        </manifest>  
                    </archive>  
                    <descriptorRefs>  
                        <descriptorRef>jar-with-dependencies</descriptorRef>  
                    </descriptorRefs>  
                </configuration>  
            </plugin>  
        </plugins>  
    </build>

然后在当前项目下执行mvn assembly:assembly, 执行成功后会在target文件夹下多出一个以-jar-with-dependencies结尾的JAR包. 这个JAR包就包含了项目所依赖的所有JAR包。

优劣

  1. 方法1的缺点在于如果编译环境和运行环境存在比较大的差异,即运行环境缺少比较多的依赖,我们就需要一步一步将依赖添加到集群中,比较麻烦,同时加添加到集群的依赖也许在该任务下使用没有问题,但其他任务可能不需要或者需要不同版本的依赖,会造成一定的麻烦。好处在于添加到集群的依赖都是确实本项目需要的,可以保证本任务运行时有相对干净的环境。该方法比较适合测试环境只有自己在使用的场景。
  2. 方法2的有点是非常方便,简单粗暴地一次将所有依赖打入jar包,保证依赖只多不少,就算依赖多了,也只是影响自己的任务,不会影响集群中其他任务的依赖。缺点在于可能将一些集群不需要的,重复的依赖包在一起,可能在运行期出现依赖冲突jar包中的依赖和集群原始的依赖有冲突,这样就需要进一步进行排查和解决。该方法比较适合公用集群,需要保证集群相对干净的情况
posted @ 2017-03-22 12:59  QZM  阅读(201)  评论(0编辑  收藏  举报