SpringBoot升级至3.2.4/3.2.5启动失败:jvm_info指标已被占用
问题描述
将Spring Boot从v3.2.3版本升级至v3.2.4或v3.2.5版本后,应用无法启动,核心报错为:
Failed to register Collector of type MicrometerCollector: jvm_info is already in use by another Collector of type VersionInfoExports
完整启动日志如下:
2024-04-23T15:40:33.927+02:00 WARN 4252 --- [CMF] [ main] ConfigServletWebServerApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: java.lang.IllegalArgumentException: Failed to register Collector of type MicrometerCollector: jvm_info is already in use by another Collector of type VersionInfoExports 2024-04-23T15:40:33.928+02:00 INFO 4252 --- [CMF] [ main] SEM-LOG : 23/04/2024 15:40:33~|~303017220~|~N/A~|~N/A~|~uh14zs~|~N/A~|~N/A~|~Process fso on localhost/192.168.1.238 has stopped~|~N/A~|~N/A~|~N/A~|~fso 2024-04-23T15:40:33.936+02:00 INFO 4252 --- [CMF] [ main] .a.t.c.t.h.i.WaitForCloseListeningServer : Stopping Administration endpoint server at /[0:0:0:0:0:0:0:0]:10081 2024-04-23T15:40:33.941+02:00 INFO 4252 --- [CMF] [ main] .a.t.c.t.h.i.WaitForCloseListeningServer : Administration endpoint stopped 2024-04-23T15:40:33.942+02:00 WARN 4252 --- [CMF] [Netty 4 Timer-1] c.i.a.m.a.probe.ProbeRegistry : ReadinessProbe Spring-Context-Initialized failed 2024-04-23T15:40:33.942+02:00 WARN 4252 --- [CMF] [Netty 4 Timer-1] c.i.a.m.a.probe.ProbeRegistry : ReadinessProbe WarmupExecutingProbe failed 2024-04-23T15:40:33.945+02:00 WARN 4252 --- [CMF] [ main] o.s.b.f.support.DisposableBeanAdapter : Invocation of close method failed on bean with name 'tracer': java.lang.AbstractMethodError: Receiver class io.opentracing.util.GlobalTracer does not define or inherit an implementation of the resolved method 'abstract void close()' of interface java.lang.AutoCloseable. 2024-04-23T15:40:33.951+02:00 INFO 4252 --- [CMF] [ main] o.apache.catalina.core.StandardService : Stopping service [Tomcat] 2024-04-23T15:40:33.955+02:00 WARN 4252 --- [CMF] [ main] o.a.c.loader.WebappClassLoaderBase : The web application [fso] appears to have started a thread named [Timer-0] but has failed to stop it. This is very likely to create a memory leak. Stack trace of thread: java.base/java.lang.Object.wait0(Native Method) java.base/java.lang.Object.wait(Object.java:366) java.base/java.util.TimerThread.mainLoop(Timer.java:563) java.base/java.util.TimerThread.run(Timer.java:516) 2024-04-23T15:40:33.973+02:00 INFO 4252 --- [CMF] [ main] .s.b.a.l.ConditionEvaluationReportLogger : Error starting ApplicationContext. To display the condition evaluation report re-run your application with 'debug' enabled. 2024-04-23T15:40:33.987+02:00 ERROR 4252 --- [CMF] [ main] o.s.boot.SpringApplication : Application run failed java.lang.IllegalArgumentException: Failed to register Collector of type MicrometerCollector: jvm_info is already in use by another Collector of type VersionInfoExports at io.prometheus.client.CollectorRegistry.register(CollectorRegistry.java:57) at io.prometheus.client.Collector.register(Collector.java:307) at io.micrometer.prometheus.PrometheusMeterRegistry.lambda$applyToCollector$18(PrometheusMeterRegistry.java:581) at java.base/java.util.concurrent.ConcurrentHashMap.compute(ConcurrentHashMap.java:1955) at io.micrometer.prometheus.PrometheusMeterRegistry.applyToCollector(PrometheusMeterRegistry.java:576) at io.micrometer.prometheus.PrometheusMeterRegistry.newGauge(PrometheusMeterRegistry.java:334) at io.micrometer.core.instrument.MeterRegistry.lambda$gauge$4(MeterRegistry.java:324) at io.micrometer.core.instrument.MeterRegistry.lambda$registerMeterIfNecessary$8(MeterRegistry.java:583) at io.micrometer.core.instrument.MeterRegistry.getOrCreateMeter(MeterRegistry.java:638) at io.micrometer.core.instrument.MeterRegistry.registerMeterIfNecessary(MeterRegistry.java:590) at io.micrometer.core.instrument.MeterRegistry.registerMeterIfNecessary(MeterRegistry.java:583) at io.micrometer.core.instrument.MeterRegistry.gauge(MeterRegistry.java:324) at io.micrometer.core.instrument.Gauge$Builder.register(Gauge.java:195) at io.micrometer.core.instrument.binder.jvm.JvmInfoMetrics.bindTo(JvmInfoMetrics.java:38) at org.springframework.boot.actuate.autoconfigure.metrics.MeterRegistryPostProcessor.lambda$applyBinders$1(MeterRegistryPostProcessor.java:149) at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:183) at java.base/java.util.ArrayList.forEach(ArrayList.java:1511) at java.base/java.util.stream.SortedOps$RefSortingSink.end(SortedOps.java:395) at java.base/java.util.stream.Sink$ChainedReference.end(Sink.java:258) at java.base/java.util.stream.Sink$ChainedReference.end(Sink.java:258) at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:510) at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499) at java.base/java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:150) at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:173) at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234) at java.base/java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:596) at org.springframework.boot.actuate.autoconfigure.metrics.MeterRegistryPostProcessor.applyBinders(MeterRegistryPostProcessor.java:149) at java.base/java.lang.Iterable.forEach(Iterable.java:75) at org.springframework.boot.actuate.autoconfigure.metrics.MeterRegistryPostProcessor.afterSingletonsInstantiated(MeterRegistryPostProcessor.java:92) at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:986) at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:962) at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:624) at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:146) at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:754) at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:456) at org.springframework.boot.SpringApplication.run(SpringApplication.java:334) at org.springframework.boot.SpringApplication.run(SpringApplication.java:1354) at org.springframework.boot.SpringApplication.run(SpringApplication.java:1343) at nl.ing.cbp.fso.FsoApplicationKt.main(FsoApplication.kt:20)
应用主程序代码:
import org.springframework.boot.autoconfigure.SpringBootApplication import org.springframework.boot.builder.SpringApplicationBuilder import org.springframework.boot.runApplication import org.springframework.boot.web.servlet.support.SpringBootServletInitializer @SpringBootApplication class FsoApplication : SpringBootServletInitializer() { override fun configure(builder: SpringApplicationBuilder): SpringApplicationBuilder { return builder.sources(FsoApplication::class.java) } } fun main(args: Array<String>) { @Suppress("SpreadOperator") runApplication<FsoApplication>(*args) }
问题成因
- Spring Boot 3.2.4/3.2.5升级了Micrometer依赖版本,Micrometer的
JvmInfoMetrics组件会自动注册jvm_info指标; - 应用中同时引入了Prometheus的
VersionInfoExports组件(通常来自io.prometheus:simpleclient_hotspot或关联依赖),该组件也会注册同名的jvm_info指标; - Prometheus的
CollectorRegistry不允许同名指标重复注册,导致启动时触发冲突异常。
可行解决办法
方法一:禁用Spring Boot自动配置的JvmInfoMetrics
在配置文件中添加开关:
management.metrics.binders.jvm.info.enabled=false
或者在启动类上排除对应自动配置类:
@SpringBootApplication(exclude = [JvmInfoMetricsAutoConfiguration::class]) class FsoApplication : SpringBootServletInitializer() { // 原有代码不变 }
方法二:移除Prometheus的VersionInfoExports依赖
如果不需要Prometheus原生的JVM版本指标,可以排除相关依赖。例如Maven中:
<dependency> <groupId>io.prometheus</groupId> <artifactId>simpleclient_hotspot</artifactId> <exclusions> <exclusion> <groupId>io.prometheus</groupId> <artifactId>simpleclient</artifactId> </exclusion> </exclusions> </dependency>
若该指标非必需,也可直接移除simpleclient_hotspot依赖。
方法三:自定义CollectorRegistry隔离指标
创建独立的CollectorRegistry实例,将Micrometer和Prometheus的指标分别注册到不同实例中,避免冲突:
@Configuration class MetricsConfig { @Bean fun prometheusMeterRegistry(): PrometheusMeterRegistry { val registry = PrometheusMeterRegistry(PrometheusConfig.DEFAULT) // 手动绑定需要的指标,跳过JvmInfoMetrics return registry } @Bean fun customCollectorRegistry(): CollectorRegistry { val registry = CollectorRegistry() // 将Prometheus原生VersionInfoExports注册到独立实例 VersionInfoExports().register(registry) return registry } }
方法四:升级到Spring Boot 3.2.6及以上版本
Spring Boot后续版本可能已修复该指标冲突问题,检查官方发布日志确认后,升级到更高版本即可解决。
内容的提问来源于stack exchange,提问作者user24613183
相关产品推荐
相关产品推荐

