解决jar包冲突导致的NoSuchMethodException或NoSuchFieldError异常
问题背景:
使用spark datasource v2 接口,外接存储源时,发现更改项目版本后,spark-shell报错
搜索该错误无果,网上报什么window util错,并不是我遇到的问题.
error: not found: value spark
Exception in thread "main" java.lang.NoSuchMethodError: org.apache.spark.package$.SPARK_VERSION()Ljava/lang/String;
分析:
显然,存在报错提示包冲突,从spark-2.4.5-bin-hadoop2.7/jars 移除自己的jar包文件后,./bin/spark-shell 可以正常执行。
查看自己的jar包信息,jar -vtf xxx.jar 发现奇怪的org/apache/spark/package.class和org/apache/spark/package$.class,
怀疑这package的.class导致,修改自己代码的包结构,编译仍然出现。
解决方法:
通过maven 插件,排除org/apache/spark/package.class和org/apache/spark/package$.class。 不够还不知道为何会产生这个package.class
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-shade-plugin</artifactId> <version>2.4.3</version> <executions> <execution> <phase>package</phase> <goals> <goal>shade</goal> </goals> <configuration> <artifactSet> <excludes> <exclude>org.slf4j:*</exclude> <exclude>log4j:*</exclude> <exclude>org.apache.spark:*</exclude> <exclude>org.apache.hadoop:*:jar:</exclude> </excludes> </artifactSet> <filters> <filter> <artifact>*:*</artifact> <excludes> <exclude>META-INF/*.SF</exclude> <exclude>META-INF/*.DSA</exclude> <exclude>META-INF/*.RSA</exclude> <exclude>log4j.properties</exclude> <exclude>org/apache/spark/network/util/**</exclude> <exclude>com/fasterxml/jackson/**</exclude> <exclude>org/apache/spark/package$.class</exclude> <exclude>org/apache/spark/package.class</exclude> <!--exclude>org/apache/spark/util/**</exclude--> </excludes> </filter> </filters> <transformers> <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer"> <resource>reference.conf</resource> </transformer> <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer"/> <transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/> </transformers> </configuration> </execution> </executions> </plugin>
其他:
1. JVM 加载 jar的顺序成迷
XX-1.0-SNAPSHOT.jar 在classpath的末尾,而XX-1.1.1.jar的将在前面,用stat XX-1.1.1.jar 和XX-1.0-SNAPSHOT.jar查看inode,也是大于spark-core_2.11-2.4.5.jar的inode编号。所以网上说的和inode系统有关,也未验证成功。
修改jar包名也未改变在classpath中的顺序。
2. 使用--jars XXX.jar 在classpath的最后,后加载也可以避免该问题。