【发布时间】:2018-03-30 12:42:21
【问题描述】:
我正在使用 Spring Boot 和 JPA Hibernate。 我正在监视 Heap 的服务,发现我的每个请求都占用了大约 40-50 MB。
所以内存增加了,在几次请求 GC 运行后,它释放了内存,这将永远持续下去。
所以我的第一个问题是这是内存泄漏吗?
我也在试图找出造成这种情况的原因。因此,我使用 Runtime.getRuntime() freeMemory 和 totalMemory() 来确定在获取一个 db 调用并使用它填充投影时使用了大约 15MB
public interface RecommendationProjection {
public String getType();
public boolean getIsOK();
public int getId();
public int getTagCount();
public double getQuality() ;
public LocalDateTime getLastActivity();
}
并且休眠返回 567 条记录,所以基本上我从 DB 得到的是上面投影的 567 列表,但我不明白这个对象怎么会占用这么高的内存?是休眠造成的吗?
使用投影时,休眠查询特定字段还是从数据库中获取所有字段?
然后我将此域映射到 DTO,它再次使用 15-20MB 内存? 这是我的 DTO
public class RecommendationInfoDTO {
private String type;
private boolean isOK;
private int id;
private int tagCount;
private double quality ;
@JsonFormat(shape=JsonFormat.Shape.STRING, pattern="yyyy-MM-dd HH:mm:ss", timezone="IST")
private LocalDateTime lastActivity;
.. getters and setters
}
仅供参考:我使用 VisualVM 进行监控。 谁能告诉我可能是什么问题?
我也分析了堆转储但什么都没有?
这是我的堆转储差异。
我在一个请求中触发了 6 个休眠查询和 3 个简单的普通 mysql 查询(使用 jdbc 调用)
问题只是 1 个休眠调用。我认为我的休眠有问题? 有什么方法可以进行基于请求的分析吗?
Gc / 内存图
按大小排序的堆转储
【问题讨论】:
-
您使用哪个版本的 Java?
-
您能否发布您获取数据的方式(任何存储库类、自定义查询等)?您应该做的第一件事是确定您的预测是否正常工作。记录您的休眠生成语句,并查看是否选择了所有列或仅选择了投影声明的列。
-
你能显示根据最后一列(即大小)排序的堆转储吗?
-
您使用的最小和最大堆大小是多少?您的应用程序运行了多长时间以及您向应用程序发出了多少请求?您是否收到任何 OOM 错误?你能不能也给你看一下GC图。
-
我使用的是 Java 8,我已经看到查询投影工作正常。查询仅获取特定的记录。最小堆 512M 和最大堆 1024M。我在本地测试它。如此单一(没有任何使用 40MB 的并发请求)