包冲突解决之-invalid constant type: 18

文章描述了一种情况,服务由于缺少名为xxx的Springbean而无法启动,经排查发现是由于使用Reflections扫描包时,不支持MyBean中使用Stream的特性。升级Reflections的Javassist版本后解决了问题,但又引出jar包加载顺序导致的意外重启成功率问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  1. 背景
    1. 现象一:引入了一个包A,服务突然起不来了,后台有报错信息,Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'xxx' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}
    2. 现象二:多次重启服务,有一定的概率能够启动(初步怀疑是包冲突)
    3. 启动不了的时候,报错的bean写法如下
      1. package mypackage;
        
        @Slf4j
        @MyComponent
        @RequiredArgsConstructor(onConstructor = @__(@Autowired))
        public class MyBean{
        XXX
        }
    4. 上述他使用自己定义的注意,然后通过自定义的beanDefinitionRegistar扫描这类bean
      public class MyComponentConfigRegister implements ImportBeanDefinitionRegistrar {
      
          public void registerBeanDefinitions(@NotNull AnnotationMetadata importingClassMetadata, @NotNull BeanDefinitionRegistry registry) {
            
              //获取到所有包含这些注解的类之后,我们添加到spring容器中去即可
              Set<Class<?>> annotated = new Reflections(new ConfigurationBuilder().forPackage("mypackage").setScanners(Scanners.values())).get(TypesAnnotated.with(MyComponent.class).asClass());    
      }
  2. 初步追查,bean找不到问题
    1. 现象很简单,spring中最常见的问题了,少了一个bean;背景也只自定义一个beanDefinitionRegsitar扫描背@MyComponent注明的类。
    2. debug这个MyComponentConfigRegister 。发现了一个很奇怪的问题,
      1. 核心代码, Set<Class<?>> annotated = new Reflections(new ConfigurationBuilder().forPackage("mypackage").setScanners(Scanners.values())).get(TypesAnnotated.with(MyComponent.class).asClass());    
      2. 扫描出来的annotated就是没有MyBean这个类
      3. 可以观察到他的反射包使用的是Reflections类,来自jar包reflections
    3. 问题是,为啥包里面没有有这个类MyBean,通过Reflections就是扫描不到呢??
    4. debug过程中,另外发现一个问题,同一个包路径下的类,MyBean1,就是可以被扫描到,但是Mybean就是不行。
      package mypackage;
      
      @Slf4j
      @MyComponent
      @RequiredArgsConstructor(onConstructor = @__(@Autowired))
      public class MyBean1{
      XXX
      }
  3. 继续追查,Reflections获取不到反射的问题
    1. debug Reflections类,在他的scan方法里面初见端倪,
    2. 处理mybean的时候,会报错误,invalid constant type: 18; 看下这个错误具体是哪边报出来的;继续debug;
      1. 进入方法,javassist.bytecode.ClassFile#read
      2. 进入方法,javassist.bytecode.ConstPool#read
      3. 进入方法,javassist.bytecode.ConstPool#readOne
      4. 报错内容,
      5. 可以看到,是javassist在获取类的常量池的时候,不认识18的类型。18是什么东西呢。
        1. 类型是CONSTANT_InvokeDynamic_info,他是一个数据结构,表示的是i字节码指令InvokeDynamic的具体的信息。 典型的java代码,例如lumda表达是编译出来的字节码就会是invokeDynamic指令
    3. 因为,日志级别是trace,所以服务器日志上看不到这个错误信息。
  4. 继续追查,invalid constant type: 18,是什么问题
    1. stackoverflow上已经有类似的问题,Reflections - Java 8 - invalid constant type - Stack Overflow
    2. ​​​​​​帖子的结论很简单:Reflections依赖的javassist版本太低了,不支持java8的特性。例如stream的使用
    3. 至此,问题定位到。而且Mybean的写法和MYbean1的写法中区别就是,myBean使用了stream,所以Reflections在扫描的时候报错了。
      1.         
        package mypackage;
        
        @Slf4j
        @MyComponent
        @RequiredArgsConstructor(onConstructor = @__(@Autowired))
        public class MyBean{
            public void method(String testTelephones) {
                Arrays.stream(testTelephones.split(",")).map(String::trim).collect(Collectors.toList());
            }
        }
        
  5. 问题解决:
    1. 升级Reflections依赖的javassit的版本
  6. 继续:
    1. 到这里问题应该解决了,发布代码问题也确实解决了。
    2. 但是,,,好像还有一个遗留的疑问,最开始的时候,为啥重启多次也能解决呢。
    3. 看看最初的版本依赖,,其第一个有问题的jar包路径更短。理论上是100%错误,不应该重启多次就好
    4. 最终发现,2个包的坐标不一样,他们的groupid不一致导致的,2个jar包不会报冲突,在jvm启动时加载那个jar包都有一定的几率,
0: jdbc:hive2://localhost:10000/default> select count(*) from party; INFO : Compiling command(queryId=stu_20250614034450_e4e8b591-67e8-49a9-a0a1-a1ed84cdab83): select count(*) from party INFO : Semantic Analysis Completed (retrial = false) INFO : Created Hive schema: Schema(fieldSchemas:[FieldSchema(name:_c0, type:bigint, comment:null)], properties:null) INFO : Completed compiling command(queryId=stu_20250614034450_e4e8b591-67e8-49a9-a0a1-a1ed84cdab83); Time taken: 0.126 seconds INFO : Concurrency mode is disabled, not creating a lock manager INFO : Executing command(queryId=stu_20250614034450_e4e8b591-67e8-49a9-a0a1-a1ed84cdab83): select count(*) from party WARN : Hive-on-MR is deprecated in Hive 2 and may not be available in the future versions. Consider using a different execution engine (i.e. tez) or using Hive 1.X releases. INFO : Query ID = stu_20250614034450_e4e8b591-67e8-49a9-a0a1-a1ed84cdab83 INFO : Total jobs = 1 INFO : Launching Job 1 out of 1 INFO : Starting task [Stage-1:MAPRED] in serial mode INFO : Number of reduce tasks determined at compile time: 1 INFO : In order to change the average load for a reducer (in bytes): INFO : set hive.exec.reducers.bytes.per.reducer=<number> INFO : In order to limit the maximum number of reducers: INFO : set hive.exec.reducers.max=<number> INFO : In order to set a constant number of reducers: INFO : set mapreduce.job.reduces=<number> INFO : number of splits:1 INFO : Submitting tokens for job: job_local849148416_0004 INFO : Executing with tokens: [] INFO : The url to track the job: http://localhost:8080/ INFO : Job running in-process (local Hadoop) INFO : 2025-06-14 03:44:51,641 Stage-1 map = 0%, reduce = 0% ERROR : Ended Job = job_local849148416_0004 with errors ERROR : FAILED: Execution Error, return code 2 from org.apache.hadoop.hive.ql.exec.mr.MapRedTask INFO : MapReduce Jobs Launched: INFO : Stage-Stage-1: HDFS Read: 0 HDFS Write: 0 FAIL INFO : Total MapReduce CPU Time Spent: 0 msec INFO : Completed executing command(queryId=stu_20250614034450_e4e8b591-67e8-49a9-a0a1-a1ed84cdab83); Time taken: 1.295 seconds Error: Error while compiling statement: FAILED: Execution Error, return code 2 from org.apache.hadoop.hive.ql.exec.mr.MapRedTask (state=08S01,code=2)
06-15
n file included from src/lab1/step1/step1.c:1:0: src/lab1/step1/../linklist.h: In function ‘addPoly’: src/lab1/step1/../linklist.h:62:7: error: expected identifier or ‘(’ before numeric constant PNODE 1=polyAddLeft->next; ^ src/lab1/step1/../linklist.h:65:8: warning: comparison between pointer and integer while(1!=NULL && r!=NULL) ^~ src/lab1/step1/../linklist.h:67:7: error: invalid type argument of ‘->’ (have ‘int’) if(1->exp==r->exp) ^~ src/lab1/step1/../linklist.h:70:16: error: invalid type argument of ‘->’ (have ‘int’) temp->exp=1->exp; ^~ src/lab1/step1/../linklist.h:71:17: error: invalid type argument of ‘->’ (have ‘int’) temp->coef=1->coef+r->coef; ^~ src/lab1/step1/../linklist.h:75:8: error: invalid type argument of ‘->’ (have ‘int’) 1=1->next; ^~ src/lab1/step1/../linklist.h:78:12: error: invalid type argument of ‘->’ (have ‘int’) else if(1->exp < r->exp) ^~ src/lab1/step1/../linklist.h:81:16: error: invalid type argument of ‘->’ (have ‘int’) temp->exp=1->exp; ^~ src/lab1/step1/../linklist.h:82:17: error: invalid type argument of ‘->’ (have ‘int’) temp->coef=1->coef; ^~ src/lab1/step1/../linklist.h:86:8: error: invalid type argument of ‘->’ (have ‘int’) 1=1->next; ^~ src/lab1/step1/../linklist.h:98:7: warning: comparison between pointer and integer if(1==NULL) sign=r; ^~ src/lab1/step1/../linklist.h:99:20: warning: assignment makes pointer from integer without a cast [-Wint-conversion] if(r==NULL) sign=1; ^ src/lab1/step1/../linklist.h: In function ‘printPoly’: src/lab1/step1/../linklist.h:132:7: error: expected ‘;’ before ‘printf’ printf("%dx^%d",p->coef,p->exp) ^~~~~~
03-21
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值