使用下面的Recursive方法获取java.lang.OutOfMemoryError异常

问题描述 投票:1回答:4

enter image description here基本上,方法是遍历节点并创建类似结构的图形。更多的400K对象正在创建,导致OutOfMemoryError。有人可以帮助优化下面的代码。

方法 :

    private static PolicyNodeInfo[] mapPolicySteps(PolicyTreatmentNodeInfo fromObj)
 {

    List<PolicyNodeInfo> tmpList = new ArrayList<PolicyNodeInfo>();
    PolicyTreatmentNodeInfo[] childrens = fromObj.getChildrenPolicyInfo(); 
    // Get object policy node children

    if(childrens != null) //if there are no children return empty list
    {
        for(PolicyTreatmentNodeInfo child : childrens) 
        //for each children map the object and recursively go over his children
        {
            if(null!=child)
             {
                if(X3ServerUtil.isStringNotEmptyNotNull(child.getStepName())&& 
                   !child.getStepName().startsWith("Dummy")) 
             //case child is not null (edge) or it's not non operation step (need to ignore)
                    {   
                    int index = tmpList.size();
                    tmpList.add(insertStep(child)); //insert current node

                    tmpList.get(index).setPolicyTreatmentNodeInfoList(mapPolicySteps(child)); 
                    //insert recursively all child nodes
                }
                else
                {
                handleDummyChildNodeInsertion(tmpList, child);
                }
            }
        }
    }
        return tmpList.toArray(new PolicyNodeInfo[tmpList.size()]);
}

例外:(Stack.java:23)weblogic.kernel.ThreadLocalStack $ StackInitialValue.initialValue(ThreadLocalStack.java:159)at weblogic.kernel.FinalThreadLocal $ FinalThreadStorage。(FinalThreadLocal.java:208)at weblogic.kernel.AuditableThread。(AuditableThread .java:13)截断。查看日志文件以获取完整的堆栈跟踪

图结构类似于下面的一个,有49个节点。并且由于多路径可能,方法被称为超过400K次..

java recursion out-of-memory
4个回答
0
投票

递归对于遍历大数据集是危险的,因为堆栈内存实际上不在您的控制之下。 (换句话说:我在学校学习递归是一种“最优雅”的解决方案,在大学里学习“不做” - 去图......)

要消除这种情况,请使用合适的数据结构进行展开,例如这些行的队列:

Deque<MyObject> queue = ...
queue.push(rootElement);
while (!queue.isEmpty()) {
    MyObject currentElement = queue.poll();
    // ... process current element
    // and in the end: push children
    currentElement.getChildren().forEach(child -> queue.push(child));
}

对于深度优先遍历,使用堆栈代替(即pop()而不是poll());

如果这仍然给你带来内存不足的错误,你要么必须增加堆空间,要么全部使用不同的方法。


0
投票

问题是在这行tmpList.get(index).setPolicyTreatmentNodeInfoList(mapPolicySteps(child));这里调用的顺序是mapPolicySteps(child)首先调用,只有当它返回.setPolicyTreatmentNodeInfoList(/*Whatever returns from mapPolicySteps(child)*/)被调用时。这会产生很多堆栈帧,等待mapPolicySteps函数结束。

你需要找出一种方法,使mapPolicySteps函数最后调用。 (被称为Tail call / Tail recursion


0
投票

谢谢你的帮助。一直试图解决这个问题,并提出了以下解决方案,这是正常的。发布以下答案。 :)

  //Created a class level hashmap
public static Map<String,PolicyNodeInfo> executedElementMap=new HashMap<String,PolicyNodeInfo>();  

// Whichever node is being traversed is stored in the map.
// Before Traversing any node , just checking whether the node has already been traversed , if traversed just add the node and skip the traversing.

private static PolicyNodeInfo[] mapPolicySteps(PolicyTreatmentNodeInfo fromObj)

{
    List<PolicyNodeInfo> tmpList = new ArrayList<PolicyNodeInfo>();
    PolicyTreatmentNodeInfo[] childrens = fromObj.getChildrenPolicyInfo(); // Get object policy node children
    if(childrens != null) //if there are no children return empty list
    {
        for(PolicyTreatmentNodeInfo child : childrens) //for each children map the object and recursively go over his children
        {
            if(null!=child)
                {
                Boolean isNodeTraversed= executedElementMap.containsKey(child.getStepName());
                  if(!isNodeTraversed)
                  {
                    executedElementMap.put(child.getStepName(), child);
                    if(X3ServerUtil.isStringNotEmptyNotNull(child.getStepName())&& !child.getStepName().startsWith(PREFIX_FOR_NON_OPERATION_STEP)) //case child is not null (edge) or it's not non operation step (need to ignore)
                    {   
                        int index = tmpList.size();
                        tmpList.add(insertStep(child)); //insert current node
                        tmpList.get(index).setPolicyTreatmentNodeInfoList(mapPolicySteps(child)); //insert recursively all child nodes
                    }
                    else
                    {
                        handleDummyChildNodeInsertion(tmpList, child);
                    }
                 }  
                 else{
                      tmpList.add(insertStep(child));  
                     }
              }
        }
    }
    return tmpList.toArray(new PolicyNodeInfo[tmpList.size()]);
}

-1
投票
 I have faced same and resolved by using Garbage collector. There is multiple way to resolve this issue.
 1. Define scope of data members and make sure garbage collector is in picture.
 2. increase java memory for your Environment.
 https://www.wikihow.com/Increase-Java-Memory-in-Windows-7
© www.soinside.com 2019 - 2024. All rights reserved.