• 一个Hive curator-client.jar包冲突问题排查解决


    开发环境比较乱
    昨天遇到hiveserver2启动失败,查看日志报错java.lang.NoSuchMethodError: org.apache.curator.shaded.com.google.common.util.concurrent.MoreExecutors.sameThreadExecutor()

    2022-07-04T20:14:53,315 WARN  [main]: server.HiveServer2 (HiveServer2.java:startHiveServer2(1100)) - Error starting HiveServer2 on attempt 1, will retry in 60000ms
    java.lang.NoSuchMethodError: org.apache.curator.shaded.com.google.common.util.concurrent.MoreExecutors.sameThreadExecutor()Lorg/apache/curator/shaded/com/google/common/util/concurrent/ListeningExecutorService;
        at org.apache.curator.framework.listen.ListenerContainer.addListener(ListenerContainer.java:41) ~[curator-framework-2.12.0.jar:?]
        at org.apache.curator.framework.imps.CuratorFrameworkImpl.start(CuratorFrameworkImpl.java:257) ~[curator-framework-2.12.0.jar:?]
        at org.apache.hive.service.server.HiveServer2.startZookeeperClient(HiveServer2.java:484) ~[hive-service-3.1.0.3.0.1.0-187.jar:3.1.0.3.0.1.0-187]
        at org.apache.hive.service.server.HiveServer2.addServerInstanceToZooKeeper(HiveServer2.java:508) ~[hive-service-3.1.0.3.0.1.0-187.jar:3.1.0.3.0.1.0-187]
        at org.apache.hive.service.server.HiveServer2.start(HiveServer2.java:720) ~[hive-service-3.1.0.3.0.1.0-187.jar:3.1.0.3.0.1.0-187]
        at org.apache.hive.service.server.HiveServer2.startHiveServer2(HiveServer2.java:1073) [hive-service-3.1.0.3.0.1.0-187.jar:3.1.0.3.0.1.0-187]
        at org.apache.hive.service.server.HiveServer2.access$1700(HiveServer2.java:135) [hive-service-3.1.0.3.0.1.0-187.jar:3.1.0.3.0.1.0-187]
        at org.apache.hive.service.server.HiveServer2$StartOptionExecutor.execute(HiveServer2.java:1341) [hive-service-3.1.0.3.0.1.0-187.jar:3.1.0.3.0.1.0-187]
        at org.apache.hive.service.server.HiveServer2.main(HiveServer2.java:1185) [hive-service-3.1.0.3.0.1.0-187.jar:3.1.0.3.0.1.0-187]
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.8.0_181]
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[?:1.8.0_181]
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:1.8.0_181]
        at java.lang.reflect.Method.invoke(Method.java:498) ~[?:1.8.0_181]
        at org.apache.hadoop.util.RunJar.run(RunJar.java:318) [hadoop-common-3.1.1.3.0.1.0-187.jar:?]
        at org.apache.hadoop.util.RunJar.main(RunJar.java:232) [hadoop-common-3.1.1.3.0.1.0-187.jar:?]
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    发生这种错误一般都是jar包版本冲突
    正常来说,org.apache.curator.shaded.com.google.common.util.concurrent.MoreExecutors这个类应该在curator-client-2.12.0.jar中
    推测可能是存在其他版本的curator-client.jar,且MoreExecutors类中没有sameThreadExecutor方法

    hive的启动日志中会打印classpath:
    在这里插入图片描述
    这里截图只能截取到一部分,实际classpath内容非常多,路径分散于多个目录中,难于查看
    针对classpath进行搜索,并没有发现其他版本的curator-client.jar
    直接使用find命令在服务器搜寻,倒是发现好多个不同版本的jar包,逐个下载到本地反编译查看,只有pulsar目录下的org.apache.curator-curator-client-5.1.0.jar是有问题的jar包,但是这个jar包不可能被hive加载,而且也验证排除了是这个jar包的可能性

    花费了大量时间人肉搜索却得不到答案,一度开始怀疑自己。
    按照经验来说,肯定是加载了不同版本的jar包,但是却怎么也找不到

    陷入困境的时候突然想到,既然class是由JVM加载的,那JVM自己肯定知道这个class在哪个jar包中,最好就是让JVM来告诉我们答案,印象中JDK有提供的相应的API的
    网上搜了下很快就得到答案:Java通过class文件得到所在jar包

    自己新建一个maven工程来验证一下
    pom.xml:

    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
     
        <groupId>com.tianzy.test</groupId>
        <artifactId>hive_test</artifactId>
        <version>1.0-SNAPSHOT</version>
     
        <properties>
            <maven.compiler.source>8</maven.compiler.source>
            <maven.compiler.target>8</maven.compiler.target>
        </properties>
     
        <dependencies>
            <dependency>
                <groupId>org.apache.hive</groupId>
                <artifactId>hive-exec</artifactId>
                <version>3.1.2</version>
            </dependency>
        </dependencies>
     
        <build>
            <plugins>
                <plugin>
                    <!-- Build an executable JAR -->
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-jar-plugin</artifactId>
                    <version>3.1.0</version>
                    <configuration>
                        <archive>
                            <manifest>
                                <addClasspath>false</addClasspath>
    <!--                            <classpathPrefix>lib/</classpathPrefix>-->
                                <mainClass>com.tianzy.test.Test</mainClass>
                            </manifest>
                        </archive>
                    </configuration>
                </plugin>
            </plugins>
        </build>
     
    </project>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44

    Test.java

    package com.tianzy.test;
     
    public class Test {
        public static void main(String[] args) {
                String filePath = org.apache.curator.shaded.com.google.common.util.concurrent.MoreExecutors.class.getProtectionDomain().getCodeSource().getLocation().getFile();
                System.out.println(filePath);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    本地运行Test.java,输出:/D:/data/soft/apache-maven-3.6.1/repository/org/apache/curator/curator-client/2.12.0/curator-client-2.12.0.jar
    符合预期

    通过mvn package命令打包成hive_test-1.0-SNAPSHOT.jar,上传到服务器上,放到/tmp/test/目录下

    然后还要解决classpath的问题,要保证这个测试程序执行的classpath和hiveserver2的完全一样
    还好hiveserver2的启动日志中有打印classpath,直接copy出来即可
    不过由于这里的classpath非常长,手动选择copy是不可行的,不过可以通过vim命令来操作:

    先vim /var/log/hive/hiveserver2.log /tmp/test/classpath.txt
    然后定位到classpath那一行日志后,按yy复制行
    然后:n跳转到下一个文件,按p进行粘贴
    再去掉前面那些无用字符,只保留等号后面的部分
    
    (后面发现其实用jinfo pid | grep java.class.path 可以更方便拿到)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    这样/tmp/test/classpath.txt文件里面就有和hiveserver2完全相同的classpath了

    执行命令:

    cd /tmp/test
    CLASSPATH=`cat classpath.txt`
    export CLASSPATH=$CLASSPATH:/tmp/test/hive_hook_test-1.0-SNAPSHOT.jar
    java com.tianzy.test.Test
    
    • 1
    • 2
    • 3
    • 4

    输出:/data/hdp/3.0.1.0-187/hbase/lib/geomesa-hbase-distributed-runtime-hbase2_2.11-3.4.0.jar

    下载下来反编译查看:
    在这里插入图片描述
    可以看到这个jar包里面确实是有org.apache.curator.shaded.com.google.common.util.concurrent.MoreExecutors这个类,但是类里面没有sameThreadExecutor方法
    比较过分的是,这是一个fat jar,把它所依赖的一些jar包全打在了这个jar包里面
    一般来说fat jar是用来作为独立jar包运行,而不应该作为依赖包被引入

    这个jar包是有人之前做测试的时候弄的,现在已经不用了
    直接删掉这个jar包,然后再启动hiveserver2,可以正常启动了

  • 相关阅读:
    【趣味随笔】YOLO的“进化史”极简版(YOLO v1-->YOLOP)
    (三)基于docker-compose的微服务编排实践-搭建nacos
    怎么把图片转换成ico图标文件?
    软件著作权申请材料及申请流程?
    【1282. 用户分组】
    Sharding sphere分库分表
    springboot+微信小程序基于微信小程序的化妆品商城系统设计与实现毕业设计源码041152
    单元测试我们需要知道哪些?
    基于Android的天气预报系统的设计与实现
    非零基础自学Java (老师:韩顺平) 第8章 面向对象编程(中级部分) 8.12 Object类详解
  • 原文地址:https://blog.csdn.net/li281037846/article/details/125614518