【发布时间】:2016-05-09 14:30:28
【问题描述】:
由于高堆分配,我面临内存不足的问题。我通过 HP 诊断工具对其进行了验证,它指向我的代码中我在数组列表中添加元素的部分。我无法弄清楚我还能如何编写此代码以便尽早释放对象。下面是代码:
private List<UpperDTO> populateRecords(List<BaseEntity> baseEntityList,List<DataEntity> dataEntityList) {
List<UpperDTO> masterDTOList = new ArrayList<UpperDTO>();
if(baseEntityList !=null && baseEntityList.size()>0){
BigDecimal conId = null;
for(BaseEntity baseEntity :baseEntityList){
conId = baseEntity.getConsignmentId();
ArrayList<StatusData> statusDataList = new ArrayList<StatusData>();
if(dataEntityList !=null && dataEntityList.size()>0){
for(DataEntity data : dataEntityList){
if(conId.equals(data.getConsignmentId())){
//making null to supress from the response
data.setConsignmentId(null);
statusDataList.add(TrackServiceHelper.convertStatusDataToDTO(data));
}
}
}
masterDTOList.add(TrackServiceHelper.populateDTO(baseEntity, statusDataList));
}
}
return masterDTOList;
}
public static UpperDTO populateDTO(TrackBaseEntity baseEntity,
List<StatusData> statusList) {
UpperDTO upperDTO = new UpperDTO();
//Setter methods called
upperDTO.setStatusData(statusList);
return upperDTO;
}
问题指向代码中的以下行:
masterDTOList.add(TrackServiceHelper.populateDTO(baseEntity, statusDataList));
这是从 JMS 队列接收消息的 rest api,MDB 监听这些消息。我无法在我的本地或开发环境中模拟这一点,因为问题出现在请求数量很高的性能测试期间。我该如何解决这个问题?
这是来自 HP Diagnostics 的 Collection Leak 的堆栈跟踪:
Chart Collection Class Contained Type Probe Collection Growth Rate Collection Size Leak Stack Trace Maximum Size
0, 0, 255 java.util.ArrayList com.rex.ih2.dtos.UpperDTO gtatsh645 3,848 122,312 java.util.ArrayList.add(ArrayList.java:413)
com.rex.ih2.utils.AppDAO.populateConsignment(AppDAO.java:168)
com.rex.ih2.utils.AppDAO.searchConsignment(AppDAO.java:93)
com.rex.ih2.service.AppService.fetchConDetail(AppService.java:131)
com.rex.ih2.service.AppService.getConDetail(AppService.java:69)
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:76)
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
java.lang.reflect.Method.invoke(Method.java:607)
org.apache.webbeans.intercept.InterceptorHandler.invoke(InterceptorHandler.java:297)
org.apache.webbeans.intercept.NormalScopedBeanInterceptorHandler.invoke(NormalScopedBeanInterceptorHandler.java:98)
com.rex.ih2.service.TrackService_$$_javassist_0.getConsignmentDetail(TrackService_$$_javassist_0.java)
com.rex.ih2.beans.TrackBean.action(TrackBean.java:35)
com.tnt.integration.bean.AbstractServiceBean.invokeService(AbstractServiceBean.java:259)
com.tnt.integration.bean.AbstractServiceBean.onMessage(AbstractServiceBean.java:157)
com.rex.ih2.beans.TrackBean.onMessage(TrackBean.java)
【问题讨论】:
-
这是一个比您提供的两种方法大得多的问题。恕我直言,这更像是一个设计问题而不是代码问题。我想我在这里要问的问题是,这些信息是从哪里来的,又要去哪里?您提到了 JMS 和 MDB;是否可以一次处理更小块的信息?
-
这是一个获取 API,它从消息代理接收请求消息,该消息代理具有很少的参数,必须根据这些参数在数据库中进行搜索。该搜索填充第一种方法中提到的 2 个实体。从这些实体中,我们必须填充一个 DTO,该 DTO 还具有另一个 DTO 的列表作为成员变量。然后在响应对象中设置此 DTO。
-
那么你可以应用分页什么的吗?
baseEntityList和dataEntityList到底有多大?也许您只需要更大的堆大小。 -
大部分搜索的获取记录数不超过5,所以没有放入Nopagination。baseEntityList和dataEntityList分别有15个和6个变量。在 HP Diagnostics 的 Collection Leaks 中,它显示的集合增长率为 3848,集合大小为 122312,最大大小为 143291。我不确定为什么该列表增长如此之快。即使在发送响应之后,对象是否仍然是引用。响应发送后,垃圾回收列表是否可用?
标签: java arraylist collections memory-leaks message-driven-bean