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