首页 > 解决方案 > 当 Java 对象变得太大时会发生什么?

问题描述

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

发生的事情是:

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

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

标签: javaperformanceobjectserverheap-memory

解决方案


当一个对象变得太大以至于它消耗了你所有的堆内存时,你的虚拟机将停止正常工作。在此 VM 中运行的程序的任何部分都不太可能继续正常工作。

当堆满时,垃圾收集器会尝试释放内存。他会一直尝试这样做。你的虚拟机最终将什么都不做。你很可能会得到OutOfMemoryError: GC Overhead Limit Exceeded. 见https://www.baeldung.com/java-gc-overhead-limit-exceeded

此错误不应由程序中的代码处理。如果出现内存不足错误,则不太可能有人返回null。我会认为这是非常糟糕的行为。

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

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


推荐阅读