已用堆大小不断增加

Posted

技术标签:

【中文标题】已用堆大小不断增加【英文标题】:Used heap size increasing continuously 【发布时间】:2013-09-27 10:42:07 【问题描述】:

我有 JSF Web 应用程序。我正在使用 JSF 2.1.9、Hibernate 4.1.4、GlassFish 3.1.2、PrimeFaces 3.4.1。问题是,使用的堆大小正在缓慢增加,并且在 2-3 天后达到最大堆大小。然后我必须重新启动 GlassFish。

堆转储:

一开始,我点击了应用程序中的所有网页,使用的堆大小为 100 MB:

1-2 天后,使用的堆大小增加到 300 MB(在此期间使用的网页相同):

我截取了堆中最常用的类。

char[] 类实例中,有太多这样的 SQL 查询字符串:

也许不只是一个问题,但我可能会从这个开始解决。在我的网页中,我通常从数据库中选择一些对象并渲染它。这里有一些豆子: 图片(索引控制器):

@Named("indexController")  
@SessionScoped  
public class IndexController implements Serializable   
    EntityManagerFactory emf = Persistence.createEntityManagerFactory("imagePU");  

    public List<Image> getImages()   
        EntityManager em = emf.createEntityManager();  
        List<Image> result;  
        try   
            EntityTransaction entr = em.getTransaction();  
            boolean committed = false;  
            entr.begin();  
            try   
                Query query = em.createQuery("SELECT i FROM Image i ORDER BY i.imageId DESC").setMaxResults(12);  
                result = query.getResultList();  
                entr.commit();  
                committed = true;  
             finally   
                if (!committed)   
                    entr.rollback();  
                  
              
         finally   
            em.close();  
          
        return result;  
      
  

标记图像:

@Named("galleryBean")  
@SessionScoped  
public class GalleryBean implements Serializable   

    EntityManagerFactory emf = Persistence.createEntityManagerFactory("imagePU");  

    public List<TaggedImage> getTaggedImages()   
        EntityManager em = emf.createEntityManager();  
        List<TaggedImage> result;  
        try   
            EntityTransaction entr = em.getTransaction();  
            boolean committed = false;  
            entr.begin();  
            try   
                Query query = em.createQuery("SELECT ti FROM TaggedImage ti GROUP BY ti.tag ORDER BY ti.taggedImagesId DESC");  
                result = query.getResultList();  
                entr.commit();  
                committed = true;  
             finally   
                if (!committed)   
                    entr.rollback();  
                  
              
         finally   
            em.close();  
          
        return result;  
      
  

顺便说一句,我不应该在 getter 中执行业务逻辑,但我认为这不是我的问题的主要原因。我需要帮助和一些建议。如果需要,我可以提供更多信息。

感谢您的帮助。

【问题讨论】:

【参考方案1】:

我曾经在 JSF 页面上遇到过类似的问题,经过大量研究后发现问题是 JSF 在会话中保留的视图数量。不确定这是否是您的问题,但请查看this 以配置视图数量。希望这会有所帮助。

【讨论】:

会话超时为 5 分钟。 5分钟后,这些都必须从堆中释放吗?我正在测试这个应用程序,只有 1 个活跃用户【参考方案2】:

不确定这是否能解决您的问题,但是您正在使用会话范围的支持 bean,并且基于上面的 sn-ps,实际上可能是请求范围的 bean,因为我在其中没有看到太多需要保存会话的内容。我还会考虑使用视图范围(如果可用)并重组 bean,这样您就可以从不必多次调用数据库中受益,因为 jsf 因多次调用支持 bean 而臭名昭著,就像这样。

@Named("galleryBean")  
@RequestScoped  // or @ViewScoped
public class GalleryBean implements Serializable   

    EntityManagerFactory emf = Persistence.createEntityManagerFactory("imagePU");  

    private List<TaggedImage> images = null;

    public List<TaggedImage> getTaggedImages()   
        if (this.images != null) 
            return this.images;
        
        EntityManager em = emf.createEntityManager();  
        try   
            EntityTransaction entr = em.getTransaction();  
            boolean committed = false;  
            entr.begin();  
            try   
                Query query = em.createQuery("SELECT ti FROM TaggedImage ti GROUP BY ti.tag ORDER BY ti.taggedImagesId DESC");  
                images = query.getResultList();  
                entr.commit();  
                committed = true;  
             finally   
                if (!committed)   
                    entr.rollback();  
                  
              
         finally   
            em.close();  
          
        return images;  
      
  

更好的是,如果使用漂亮的面孔和 getTaggedImages() 真的只是变得另一个 getter/setter

【讨论】:

首先,感谢您的示例代码,我需要它。而且我知道实际上我此时不需要会话范围的 bean,但我认为这些所有其他性能优化点,不是主要原因。会话超时后,必须从与会话相关的堆中释放所有内容。

以上是关于已用堆大小不断增加的主要内容,如果未能解决你的问题,请参考以下文章

为什么没有插入数据,但已用存储空间会增加

JVM 的堆大小不断增加(但 usedMemory() 不断减少)

尽管初始大小固定,但跟踪对象的 BoundingBox/ROI 的大小不断增加

内存使用率高 - 应用程序响应慢:已用内存值未减少 + 可用内存值未增加

如何管理移动应用程序中不断增加的 sqlite 大小?

使用 Aspose.Net 保存 PDF 文件大小不断增加? - 我该如何防止呢?