java.lang.IllegalArgumentException: Value must not be null异常排查
java.lang.IllegalArgumentException: Value must not be null异常排查
问题
上线新版本,系统一开始运行,系统直接报java.lang.IllegalArgumentException: Value must not be null异常具体的日志打印如下:
java.lang.IllegalArgumentException: Value must not be null
at org.springframework.util.Assert.notNull(Assert.java:198)
at org.springframework.boot.actuate.health.HealthBuilder.withDetail(Health.java:245)atnet.xmeye.vms.actuate.VersionHealthIndicator.health(VersionHealthIndicator.java:26)atorg.springframework.boot.actuate.health.HealthIndicator.getHealth(HealthIndicator.java:37)atorg.springframework.boot.actuate.health.HealthEndpointWebExtension.getHealth(HealthEndpointWebExtension.java:95)atorg.springframework.boot.actuate.health.HealthEndpointWebExtension.getHealth(HealthEndpointWebExtension.java:43)atorg.springframework.boot.actuate.health.HealthEndpointSupport.getContribution(HealthEndpointSupport.java:108)atorg.springframework.boot.actuate.health.HealthEndpointSupport.getAggregateHealth(HealthEndpointSupport.java:119)atorg.springframework.boot.actuate.health.HealthEndpointSupport.getContribution(HealthEndpointSupport.java:105)atorg.springframework.boot.actuate.health.HealthEndpointSupport.getHealth(HealthEndpointSupport.java:83)atorg.springframework.boot.actuate.health.HealthEndpointSupport.getHealth(HealthEndpointSupport.java:70)atorg.springframework.boot.actuate.health.HealthEndpointWebExtension.health(HealthEndpointWebExtension.java:81)atorg.springframework.boot.actuate.health.HealthEndpointWebExtension.health(HealthEndpointWebExtension.java:70)atsun.reflect.NativeMethodAccessorImpl.invoke0(NativeMethod)atsun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)atsun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)atjava.lang.reflect.Method.invoke(Method.java:498)atorg.springframework.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:282)atorg.springframework.boot.actuate.endpoint.invoke.reflect.ReflectiveOperationInvoker.invoke(ReflectiveOperationInvoker.java:77)atorg.springframework.boot.actuate.endpoint.annotation.AbstractDiscoveredOperation.invoke(AbstractDiscoveredOperation.java:60)atorg.springframework.boot.actuate.endpoint.web.servlet.AbstractWebMvcEndpointHandlerMappingBuilder.withDetail(Health.java:245)
at net.xmeye.vms.actuate.VersionHealthIndicator.health(VersionHealthIndicator.java:26)
at org.springframework.boot.actuate.health.HealthIndicator.getHealth(HealthIndicator.java:37)
at org.springframework.boot.actuate.health.HealthEndpointWebExtension.getHealth(HealthEndpointWebExtension.java:95)
at org.springframework.boot.actuate.health.HealthEndpointWebExtension.getHealth(HealthEndpointWebExtension.java:43)
at org.springframework.boot.actuate.health.HealthEndpointSupport.getContribution(HealthEndpointSupport.java:108)
at org.springframework.boot.actuate.health.HealthEndpointSupport.getAggregateHealth(HealthEndpointSupport.java:119)
at org.springframework.boot.actuate.health.HealthEndpointSupport.getContribution(HealthEndpointSupport.java:105)
at org.springframework.boot.actuate.health.HealthEndpointSupport.getHealth(HealthEndpointSupport.java:83)
at org.springframework.boot.actuate.health.HealthEndpointSupport.getHealth(HealthEndpointSupport.java:70)
at org.springframework.boot.actuate.health.HealthEndpointWebExtension.health(HealthEndpointWebExtension.java:81)
at org.springframework.boot.actuate.health.HealthEndpointWebExtension.health(HealthEndpointWebExtension.java:70)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:282)
at org.springframework.boot.actuate.endpoint.invoke.reflect.ReflectiveOperationInvoker.invoke(ReflectiveOperationInvoker.java:77)
at org.springframework.boot.actuate.endpoint.annotation.AbstractDiscoveredOperation.invoke(AbstractDiscoveredOperation.java:60)
at org.springframework.boot.actuate.endpoint.web.servlet.AbstractWebMvcEndpointHandlerMappingBuilder.withDetail(Health.java:245)atnet.xmeye.vms.actuate.VersionHealthIndicator.health(VersionHealthIndicator.java:26)atorg.springframework.boot.actuate.health.HealthIndicator.getHealth(HealthIndicator.java:37)atorg.springframework.boot.actuate.health.HealthEndpointWebExtension.getHealth(HealthEndpointWebExtension.java:95)atorg.springframework.boot.actuate.health.HealthEndpointWebExtension.getHealth(HealthEndpointWebExtension.java:43)atorg.springframework.boot.actuate.health.HealthEndpointSupport.getContribution(HealthEndpointSupport.java:108)atorg.springframework.boot.actuate.health.HealthEndpointSupport.getAggregateHealth(HealthEndpointSupport.java:119)atorg.springframework.boot.actuate.health.HealthEndpointSupport.getContribution(HealthEndpointSupport.java:105)atorg.springframework.boot.actuate.health.HealthEndpointSupport.getHealth(HealthEndpointSupport.java:83)atorg.springframework.boot.actuate.health.HealthEndpointSupport.getHealth(HealthEndpointSupport.java:70)atorg.springframework.boot.actuate.health.HealthEndpointWebExtension.health(HealthEndpointWebExtension.java:81)atorg.springframework.boot.actuate.health.HealthEndpointWebExtension.health(HealthEndpointWebExtension.java:70)atsun.reflect.NativeMethodAccessorImpl.invoke0(NativeMethod)atsun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)atsun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)atjava.lang.reflect.Method.invoke(Method.java:498)atorg.springframework.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:282)atorg.springframework.boot.actuate.endpoint.invoke.reflect.ReflectiveOperationInvoker.invoke(ReflectiveOperationInvoker.java:77)atorg.springframework.boot.actuate.endpoint.annotation.AbstractDiscoveredOperation.invoke(AbstractDiscoveredOperation.java:60)atorg.springframework.boot.actuate.endpoint.web.servlet.AbstractWebMvcEndpointHandlerMappingServletWebOperationAdapter.handle(AbstractWebMvcEndpointHandlerMapping.java:305)
at org.springframework.boot.actuate.endpoint.web.servlet.AbstractWebMvcEndpointHandlerMapping$OperationHandler.handle(AbstractWebMvcEndpointHandlerMapping.java:388)
分析
根据at net.xmeye.vms.actuate.VersionHealthIndicator.health(VersionHealthIndicator.java:26)找到程序中的VersionHealthIndicator类
@Component
public class VersionHealthIndicator implements HealthIndicator, ApplicationRunner {
private String version;
private String timestamp;
@Override
public Health health() {
return Health.status(Status.UP)
.withDetail("package", version)
.withDetail("buildTime", timestamp)
.build();
}
@Override
public void run(ApplicationArguments args) throws Exception {
System.out.println("VersionHealthIndicator start running");
try (InputStream inputStream = VersionHealthIndicator.class.getClassLoader()
.getResourceAsStream("packageinfo.properties")) {
Properties properties = new Properties();
properties.load(inputStream);
version = properties.getProperty("version", "");
timestamp = properties.getProperty("timestamp", "");
}
}
}
在Health.status(Status.UP).withDetail(“package”, version)抛出的异常。
继续看withDetail(“package”, version)方法, 是Assert.notNull(value, “Value must not be null”)抛出的 java.lang.IllegalArgumentException异常,并打印了"Value must not be null"。
public Builder withDetail(String key, Object value) {
Assert.notNull(key, "Key must not be null");
Assert.notNull(value, "Value must not be null");
this.details.put(key, value);
return this;
}
应该是传入的参数version的值为null。withDetail(“package”, version)方法中version参数是通过实现ApplicationRunner接口加载的。可能的原因是实现ApplicationRunner接口的VersionHealthIndicator类的run方法没有正常运行,或者是读取文件时发生了异常。但是没有报IO相关异常。
debug查看具体的执行过程
调用执行ApplicationRunner.run()、CommandLineRunner.run()的callRunners方法,会将实现了接口的类进行排序。
private void callRunners(ApplicationContext context, ApplicationArguments args) {
List<Object> runners = new ArrayList<>();
runners.addAll(context.getBeansOfType(ApplicationRunner.class).values());
runners.addAll(context.getBeansOfType(CommandLineRunner.class).values());
AnnotationAwareOrderComparator.sort(runners);
for (Object runner : new LinkedHashSet<>(runners)) {
if (runner instanceof ApplicationRunner) {
callRunner((ApplicationRunner) runner, args);
}
if (runner instanceof CommandLineRunner) {
callRunner((CommandLineRunner) runner, args);
}
}
}
具体的排序如下

会按照InitDefaultGroupRunner、SmartAdminStartupRunner、RuntimeHealthIndicator、VersionHealthIndicator依次执行。
程序执行完InitDefaultGroupRunner的run方法后,debug进入到执行SmartAdminStartupRunner的run方法,线程一直在执行SmartAdminStartupRunner的run方法。
SmartAdminStartupRunner的run方法执行了响应状态码常量的初始化,以及 aisvrService.startAnalysis()方法。
@Component
public class SmartAdminStartupRunner implements CommandLineRunner {
@Autowired
private AisvrService aisvrService;
@Override
public void run(String... args) {
ResponseCodeConst.init();
aisvrService.startAnalysis();
}
}
startAnalysis()方法中有一个while()循环,如果alarmMsgAnalysis条件变量为真,线程就会一直运行startAnalysis()方法。
public void startAnalysis() {
while (alarmMsgAnalysis) {
//代码省去
}
}
后面的RuntimeHealthIndicator、VersionHealthIndicator的run方法就都不会被执行。version变量的初始化依赖于run()方法的执行,而run()方法没有正常运行,使得version变量没有正常初始化。当执行health()方法时就会产生IllegalArgumentException异常。
问题解决
1、在实现了CommandLineRunner、ApplicationRunner接口的类上添加@Order注解,将SmartAdminStartupRunner的放在最后执行。
2、一些变量的初始化可以通过static代码块来实现。
3、将while()相关的代码开启一个新的线程执行
更多推荐



所有评论(0)