简体   繁体   中英

Facing OutOfMemory issue in Java

I am facing out of memory issue due to high heap allocation.I verified it from HP Diagnostics tool and it is pointing to a section in my code where I am adding elements in an arraylist. I am not able o figure out how else can I write this code so that objects are released early. Below is the code :

    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;

}

The issue is pointed at following line in the code :

    masterDTOList.add(TrackServiceHelper.populateDTO(baseEntity, statusDataList));

This is rest api which receives messages from JMS Queues and MDB listens to these messages. I am not able to simulate this in my local or Dev environments as the issue comes during performance testing when the number of requests are high. How can I fix this?

This is the stacktrace of Collection Leak from HP Diagnostics:

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)

I agree with dcsohi. This is actually a design problem. You may want to look at below approaches:-

1) Size of the object being added in the list. If it can be optimized. 2) Handle data in chunks instead of adding all at once in the list. 3) Optimizing JVM arguments to increase head size so that it can handle more objects.

You can try to simulate this by increasing number of test objects and reducing heap size in dev environment or maybe taking production dump and running with the same volume.

Ok, it looks to me like you only care about DataEntity objects and BaseEntity objects where their "consignment IDs" match. You really should do this sort of thing in the database query. The use of "entity" objects makes it seem like your DB interactions are via JPA/Hibernate, in which case you may want to create a DB view that joins the two tables by consignment ID, and provides the necessary information for your output. Next, create a custom read-only entity that matches this view. Then you can apply pagination to your query of this view (if it's still necessary) and retrieve the information in smaller batches.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM