使用的堆大小不断增加

时间:2013-09-22 12:46:21

标签: java hibernate jsf jsf-2 heap-memory

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

堆转储:

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

heapdumpbefore

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

heapdump after

我在堆中截取了大多数使用过的类。

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

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

@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中执行业务逻辑,但我认为这不是我问题的主要原因。我需要帮助和一些建议。如果需要,我可以提供更多信息。

感谢您的帮助。

2 个答案:

答案 0 :(得分:0)

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

答案 1 :(得分:0)

不确定这是否会解决您的问题,但是您使用会话范围支持bean并且基于上面的代码段,可能真的是请求范围的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;  
    }  
}  

更好的是,你可以将TaggedImage从数据库中实际获取并将它放在某个地方,如果使用漂亮的face和getTaggedImages()真的变成了它,那么它就会被调用为@PostConstruct或@URLAction的bean构建阶段的一部分另一个getter / setter