Java 使用的堆大小不断增加

Java 使用的堆大小不断增加,java,hibernate,jsf,jsf-2,heap-memory,Java,Hibernate,Jsf,Jsf 2,Heap Memory,我有JSFWeb应用程序。我使用的是JSF2.1.9、Hibernate4.1.4、GlassFish 3.1.2和PrimeFaces 3.4.1。问题是,使用的堆大小增长缓慢,2-3天后达到最大堆大小。那么我必须重新启动GlassFish 堆转储: 开始时,我单击应用程序中的所有网页,使用的堆大小为100 MB: 1-2天后,使用的堆大小增加到300 MB(这段时间使用的网页相同): 我拍摄了heap中最常用的类的屏幕截图 在char[]类实例中,有太多这样的SQL查询字符串: 也许不

我有JSFWeb应用程序。我使用的是JSF2.1.9、Hibernate4.1.4、GlassFish 3.1.2和PrimeFaces 3.4.1。问题是,使用的堆大小增长缓慢,2-3天后达到最大堆大小。那么我必须重新启动GlassFish

堆转储:

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

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

我拍摄了heap中最常用的类的屏幕截图

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

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

@Named(“indexController”)
@会议范围
公共类IndexController实现可序列化{
EntityManagerFactory emf=Persistence.createEntityManagerFactory(“imagePU”);
公共列表getImages(){
EntityManager em=emf.createEntityManager();
列出结果;
试试{
EntityTransaction entr=em.getTransaction();
布尔值=false;
entr.begin();
试试{
Query Query=em.createQuery(“通过i.imageId DESC从图像i顺序中选择i”).setMaxResults(12);
结果=query.getResultList();
entr.commit();
承诺=真实;
}最后{
如果(!committed){
entr.rollback();
}  
}  
}最后{
em.close();
}  
返回结果;
}  
}  
标记的图像:

@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;  
    }  
}  
@Named(“galleryBean”)
@会议范围
公共类GalleryBean实现可序列化的{
EntityManagerFactory emf=Persistence.createEntityManagerFactory(“imagePU”);
公共列表gettaggeImage(){
EntityManager em=emf.createEntityManager();
列出结果;
试试{
EntityTransaction entr=em.getTransaction();
布尔值=false;
entr.begin();
试试{
Query Query=em.createQuery(“按ti.tag ORDER BY ti.taggedImagesId DESC从TaggedImage ti组中选择ti”);
结果=query.getResultList();
entr.commit();
承诺=真实;
}最后{
如果(!committed){
entr.rollback();
}  
}  
}最后{
em.close();
}  
返回结果;
}  
}  
顺便说一下,我不应该在getters中执行业务逻辑,但我认为这不是我问题的主要原因。我需要帮助和一些建议。如果需要,我可以提供更多信息


感谢您的帮助。

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

不确定这是否能解决您的问题,但是您使用的是会话范围支持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;  
    }  
}  
@Named(“galleryBean”)
@RequestScope//或@ViewScope
公共类GalleryBean实现可序列化的{
EntityManagerFactory emf=Persistence.createEntityManagerFactory(“imagePU”);
私有列表图像=null;
公共列表gettaggeImage(){
如果(this.images!=null){
返回此图片;
}
EntityManager em=emf.createEntityManager();
试试{
EntityTransaction entr=em.getTransaction();
布尔值=false;
entr.begin();
试试{
Query Query=em.createQuery(“按ti.tag ORDER BY ti.taggedImagesId DESC从TaggedImage ti组中选择ti”);
images=query.getResultList();
entr.commit();
承诺=真实;
}最后{
如果(!committed){
entr.rollback();
}  
}  
}最后{
em.close();
}  
返回图像;
}  
}  

更好的是,如果使用漂亮的面孔和gettaggeImage()真的变成了另一个getter/setter,那么您可以将TaggedImage的实际获取从数据库中分离出来,并将其放在某个地方,作为bean构建阶段的一部分,使用@PostConstruct或@URLAction调用它。5分钟后,这些都必须从堆中释放出来,对吗?我正在测试这个只有1个活动用户的应用程序。首先,感谢您的示例代码,我需要它。我知道现在实际上我不需要会话范围的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;  
    }  
}