已用堆大小不断增加
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 的大小不断增加