由于客户端库中的一个非常愚蠢的错误,我们的生产系统存在一个特殊的问题。
发生了什么事
public <T> ResponseEntity<T> executePut(String url, JsonObject payload, Class<T> t) {
String payloadString = payload != null ? payload.toString() : null;
HttpEntity<String> entity = new HttpEntity<>(payloadString, getCommonHeaders());
restTemplate.getMessageConverters()
.add(0, new StringHttpMessageConverter(Charset.forName("UTF-8")));
return restTemplate.exchange(url, HttpMethod.PUT, entity, t);
}
从上述方法可以看出,客户端库正在使用自动装配的(单个)对象,并继续在MessageConverters列表中添加该元素。
问题:过一会儿,对restTemplate对象的引用也给NPE带来了空堆栈跟踪。
PS:我指出这是可能的原因,因为这是两次部署之间发生的唯一代码更改。
此外,大对象是否应该导致堆内存不足?在我们的案例中,这也没有发生,其他应用程序流程也完美无缺。
答案 0 :(得分:0)
当一个对象变得太大而占用了您所有的堆内存时,您的VM将停止正常工作。在此VM中运行的程序的任何部分都不太可能继续正常运行。
当堆变满时,垃圾收集器将尝试释放内存。他将一直尝试这样做。您的VM最终将无所事事。而且您很可能会得到OutOfMemoryError: GC Overhead Limit Exceeded
。参见https://www.baeldung.com/java-gc-overhead-limit-exceeded
该错误不应由程序中的代码处理。万一发生内存不足错误,某人不太可能返回null
。我认为这是非常不好的行为。
关于您的NullPointerException:我认为它没有堆栈跟踪。但是,它可能未记录。您是否尝试过将调试器附加到系统并为NPE设置异常断点?
REST模板中的所有消息转换器将被一个接一个地调用。您每次调用都会将消息转换器添加到列表的开头。这对我来说似乎没有意义。 可能在内部引起麻烦。