java - 当 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:我指出这是可能的原因,因为这是两个部署之间发生的唯一代码更改。
另外,大对象不应该导致堆内存不足吗?在我们的案例中,这也没有发生,其他应用程序流程运行完美。
解决方案
当一个对象变得太大以至于它消耗了你所有的堆内存时,你的虚拟机将停止正常工作。在此 VM 中运行的程序的任何部分都不太可能继续正常工作。
当堆满时,垃圾收集器会尝试释放内存。他会一直尝试这样做。你的虚拟机最终将什么都不做。你很可能会得到OutOfMemoryError: GC Overhead Limit Exceeded
. 见https://www.baeldung.com/java-gc-overhead-limit-exceeded
此错误不应由程序中的代码处理。如果出现内存不足错误,则不太可能有人返回null
。我会认为这是非常糟糕的行为。
关于您的 NullPointerException:我认为它没有堆栈跟踪。但是,它可能不会被记录。您是否尝试将调试器附加到系统并为 NPE 设置异常断点?
您的 REST 模板中的所有消息转换器都会被一个接一个地调用。每次调用都会将消息转换器添加到列表的开头。这对我来说似乎没有意义。它可能会在内部造成麻烦。
推荐阅读
- python - 定义字典时将字典的键存储在字典中
- kubernetes - Kubernetes Pod 没有保存数据,即使它具有持久存储
- generics - 预计如何使用 ReadWriteProperty 中的 R 泛型类型?
- variables - 模板上复杂数据结构中的ansible参数化变量
- c - 计算字符串中字符频率的程序中的 getchar
- c# - 如何按特定属性分组并按另一个属性排序?
- python - Flask - 登录蓝图不显示模块名称
- objective-c - 根据第一个字符设置某物颜色的算法
- php - 然后检查特定的列,更新或创建一个新行,pdo
- networking - 阿里云 Apache 慢转显卡