【发布时间】:2012-05-22 08:15:43
【问题描述】:
我有一个 Java EE 应用程序如下:
- 服务器在亚马逊上(大型实例,2 CPU @ 2.27GHz,8GB RAM)
- 由 Apache 直接提供的静态内容
- 在 Glassfish 3.1.1 上运行的 JSF2 (Mojarra 2.1.3) 和 JPA 2 (Eclipselink 2.3.0)
- Facelets/XHTML 从 ViewScoped 托管 bean 获取内容,这些 bean 连接到执行所有处理的 @Local Stateless EJB,包括从使用 JPA 的其他 @Local Stateless EJB 获取数据
所以通常:
XHTML --> ViewScoped Managed Bean --> Service EJB --> Data EJB --> JPA
鉴于我只运行一个 Glassfish 实例,我知道我可以/应该将 2 层 EJB 移除为一层,甚至不移除,但目前我认为这不是问题。
应用程序的性能还可以(2.2MB,包括 那时 CPU 使用了 50%,RAM 使用了 100%。
所以我运行了 JProfiler,但我不确定如何处理一种类型的结果。
在主页中,我们有一个类别列表,并且每个类别关联了许多产品(一个告诉每个类别中有多少产品的购物网站)。获取Category列表的代码是:
ViewScoped Bean
public List<Category> getLiveCategoriesInfo() {
if (liveCategories == null) {
liveCategories = liveCategoryService.getLiveCategories(getLocale().getLang().getLanguageId());
}
return liveCategories;
}
getLocale() 是从使用 ManagedProperty 注入的 SessionScoped Bean 中检索到的
服务 EJB:
public List<Category> getLiveCategories(final Integer langId) {
List<LiveCategory> lives = categoryBean.getLiveCategories(langId);
// ... some processing involving looping through the list above
return livesCategories;
}
数据 EJB:
public List<LiveCategory> getLiveCategories(final Integer langId) {
List<LiveCategory> categories = new ArrayList<LiveCategory>();
Query cq = getEntityManager().createNamedQuery(Category.FIND_LIVE);
try {
categories = cq.getResultList();
} catch (NullPointerException npe) {
// ...
}
return categories;
}
JProfiler 内存视图显示,在主页上的每个请求(即使对于同一用户),都会向内存添加一批新的类别(准确地说是 43,即显示的类别数)。类别不由 JPA 管理(来自 JPA 的列表用于“手动”创建 POJO)。
我怎样才能从内存中释放这些实体。当视图消失时,我希望它们成为 GC。但是 ViewScoped bean 本身不是 GC'd,有一堆实例留在内存中。
我应该寻找什么来释放这些对象?
- 是否在 ViewScoped bean 中使用 @ManagedProperty 来获取 SessionScoped bean 的实例以防止 ViewScoped 被 GC?
- 我应该寻找其他错误吗?
我确实查看了有关 JSF 最佳实践和性能指南的其他线程,但没有帮助。
【问题讨论】:
标签: jsf-2 memory-leaks jprofiler