Search code examples
javaarrayliststaticjvmgarbage-collection

java static list causes memory leak


I have following code which seems to be causing some memory leaks. This code snippet(i.e. hasPermissions()) get executed every time when a user performs an action.

So from what I understood, since Map permissions is a static object, all permissionsList objects that are created inside hasPermission() method have references to global static object(i.e. permissions); therefore, is not eligible to be garbage collected?

Following is the Leak Suspect showing for its heap dump in Eclipse Memory Analyzer tool. When I navigate to details, it shows the class with following code snippet. I found Java List.addAll() function internally creates LinkedList. I'm still trying to comprehend what's exactly happening here. Appreciate your thoughts.

enter image description here

public class AccessManager {
    
    
        private static Map <Integer, List> permissions;
    
        public static void init()
        {
            //initiate permissions and add values
        }
        
        public static boolean hasPermissions(List<Integer> accessLevels, String action)
        {
    
            if (permissions == null)
                init();
            
            List permissionsList = null;
            
            for (Integer a : accessLevels) {
                
                if (permissionsList == null) {
                    permissionsList = permissions.get(a);
                } else {
                    permissionsList.addAll(permissions.get(a));
                }
            }
            
            if(permissionsList.contains(action)){
                return true;
            }
            
            return false;
        }
    
    }

Solution

  • I'm going to change the code to below, so that it won't create local object: permissionList inside hasPermission(). Wondering if it would fix the issue.

    public class AccessManager {
    
    
        private static Map <Integer, List> permissions;
    
        public static void init()
        {
            //initiate permissions and add values
        }
        
        public static boolean hasPermissions(List<Integer> accessLevels, String action)
        {
    
            if (permissions == null)
                init();
                
            for (Integer a : accessLevels) {
                
                if (permissions.get(a).contains(action)) {
                    return true;
                }
            }
            
            return false;
        }
    
    }