Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/spring/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java请求占用40-50MB内存(Spring JPA Hibernate)_Java_Spring_Hibernate_Jpa - Fatal编程技术网

Java请求占用40-50MB内存(Spring JPA Hibernate)

Java请求占用40-50MB内存(Spring JPA Hibernate),java,spring,hibernate,jpa,Java,Spring,Hibernate,Jpa,我正在使用带JPA Hibernate的spring boot。 我正在监视Heap的服务,发现我的每个请求都占用了大约40-50MB的空间 因此,内存会增加,在GC运行几次请求后,它会释放内存,这将永远持续下去 所以我的第一个问题是,这是内存泄漏吗 我也在试图找出是什么导致了这一切。因此,我使用Runtime.getRuntime()freemory和totalMemory()来确定在获取一个db调用并用它填充投影时使用了大约15MB的内存 public interface Recommend

我正在使用带JPA Hibernate的spring boot。 我正在监视Heap的服务,发现我的每个请求都占用了大约40-50MB的空间

因此,内存会增加,在GC运行几次请求后,它会释放内存,这将永远持续下去

所以我的第一个问题是,这是内存泄漏吗

我也在试图找出是什么导致了这一切。因此,我使用Runtime.getRuntime()freemory和totalMemory()来确定在获取一个db调用并用它填充投影时使用了大约15MB的内存

public interface RecommendationProjection {
    public String getType();
    public boolean getIsOK();
    public int getId();
    public int getTagCount();
    public double getQuality() ;
    public LocalDateTime getLastActivity();

}
hibernate返回567条记录,所以基本上我从DB得到的是投影上面567条记录的列表,但我不明白这个对象怎么会占用这么高的内存?是冬眠造成的吗

使用投影时,hibernate查询特定字段或从数据库中获取所有字段

然后我将这个域映射到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个hibernate查询和3个简单的普通mysql查询(使用jdbc调用)

问题只是一个休眠调用。我想我的冬眠有什么问题吗? 有什么方法可以进行基于请求的分析吗

Gc/内存图

按大小排序的堆转储

以下是我的观点:

因此,内存会增加,在GC运行几次请求后,它会释放内存,这将永远持续下去

所以我的第一个问题是,这是内存泄漏吗

不一定是内存泄漏。但是,您需要运行并运行应用程序更长的时间,看看在GC周期中内存是如何释放的。只要内存使用率是一个指标,GC就能够回收垃圾,并且内存得到了有效利用

使用投影时,hibernate查询特定字段或从数据库中获取所有字段

否在投影情况下,它仅获取指定的列

然后我将这个域映射到DTO,它再次使用15-20MB内存

不仅是您的DTO,还有
hibernate
,在
spring数据之上,jpa
将在内部创建自己的对象来完成查询,这些对象可能正在等待GC。只要它们在GC循环后得到回收,并且每次GC后内存使用量没有不断增加,这就是一个健康的迹象

但是,除了每个请求所使用的内存之外,您可能还需要从更大的角度来看问题,其中一些项目(不是详尽/完整的列表)可能是:

  • 查看正常负载和峰值负载情况下一段时间内的内存使用情况
  • 次要和主要GC发生的频率以及它对应用程序的影响如何
  • 应用程序在GC中花费的时间太多了吗
  • 根据应用程序行为调整GC。例如:应用程序是否为服务请求等创建了太多的短期对象
  • 给定heap/GC配置,应用程序是否能够满足您的应用程序响应时间和吞吐量要求

  • 最后,您可能希望了解GC并对其进行调优。

    在我看来,这是正常的行为

    所以我的第一个问题是,这是内存泄漏吗

    不会。内存泄漏要求内存在其使用寿命之后保持分配状态。由于GC正在清除查询所消耗的总内存空间,因此您没有泄漏,您只是在使用内存

    但我不明白的是,这个物体怎么会有这么高的记忆

    对象没有占用太多内存,占用内存的是每个查询的567个对象实例

    让我们看一看解释原因:

    投影的每个实例都包含

    • 长度未知的
      字符串
      (字符串不是原语,因此在纯字符计数的顶部有大量的元数据属性,但就说1个字节)
    • 分配1个字节的
      布尔值
    • 每个字节的2
      int
    • 一个2字节的
      双字节
    • LocalDateTime
      ,它由几个字段组成(因此,让我们乐观地说,是2字节)
    所以每个实例至少有8个字节。 每个查询最少567*8=4536字节

    您正在对此数据集触发6个查询 4536*6=每个方法调用27216字节

    其中一些是hibernate中的开销,在调用之间会被重用,因此您不会完全看到理论上的足迹

    这与你所观察到的比较接近,所以我不认为有任何问题


    如果您希望占用更少的空间,请重新评估尽可能多地重用数据的方法,以减少必须进行的查询数量。

    您使用的是哪一版本的Java?请发布获取数据的方式(任何存储库类、自定义查询等)?您应该做的第一件事是确定投影是否正常工作。记录hibernate生成的语句,查看是否选择了所有列或仅选择了投影声明的列。是否可以显示根据最后一列(即大小)排序的堆转储?使用的最小和最大堆大小是多少?使用多长时间你已经运行了你的应用程序,你向你的应用程序发出了多少请求?你有没有收到任何OOM错误?你还可以给你看GC图。我使用Java 8,我已经看到查询投影工作正常。查询只获取特定记录。最小堆512M和最大堆1024M。我正在本地测试它。所以单(没有任何使用40MB的并发请求)我总共使用了6个查询。但只有一个查询正在执行,即获取567行。