Java对象太大时会发生什么?

时间:2019-11-21 07:57:08

标签: java performance object server heap-memory

由于客户端库中的一个非常愚蠢的错误,我们的生产系统存在一个特殊的问题。

发生了什么事

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:我指出这是可能的原因,因为这是两次部署之间发生的唯一代码更改。

此外,大对象是否应该导致堆内存不足?在我们的案例中,这也没有发生,其他应用程序流程也完美无缺。

1 个答案:

答案 0 :(得分:0)

当一个对象变得太大而占用了您所有的堆内存时,您的VM将停止正常工作。在此VM中运行的程序的任何部分都不太可能继续正常运行。

当堆变满时,垃圾收集器将尝试释放内存。他将一直尝试这样做。您的VM最终将无所事事。而且您很可能会得到OutOfMemoryError: GC Overhead Limit Exceeded。参见https://www.baeldung.com/java-gc-overhead-limit-exceeded

该错误不应由程序中的代码处理。万一发生内存不足错误,某人不太可能返回null。我认为这是非常不好的行为。

关于您的NullPointerException:我认为它没有堆栈跟踪。但是,它可能未记录。您是否尝试过将调试器附加到系统并为NPE设置异常断点?

REST模板中的所有消息转换器将被一个接一个地调用。您每次调用都会将消息转换器添加到列表的开头。这对我来说似乎没有意义。 可能在内部引起麻烦。