java静态列表导致内存泄漏

Anu*_*dha 0 java static garbage-collection jvm arraylist

我有以下代码似乎导致一些内存泄漏。每次用户执行操作时都会执行此代码片段(即 hasPermissions())。

因此,根据我的理解,由于 Map权限是静态对象,因此在hasPermission()方法 内创建的所有PermissionsList对象都引用全局静态对象(即Permissions);那么,是不是没有资格被垃圾收集呢?

以下是 Eclipse Memory Analyzer 工具中显示的泄漏嫌疑人的堆转储。当我导航到详细信息时,它显示带有以下代码片段的类。我发现 Java List.addAll()函数在内部创建LinkedList。我仍在尝试理解这里到底发生了什么。欣赏你的想法。

在此输入图像描述

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;
        }
    
    }
Run Code Online (Sandbox Code Playgroud)

mer*_*ike 8

该代码已被严重破坏。在向List引用的对象添加新权限时permissions,该hasPermission方法不仅会造成内存泄漏,还可能导致后续访问检查被错误授予,这可能是一个相当严重的安全漏洞。

例如,如果permissions包含

钥匙 价值
1 [A]
2 [b]

并且您执行hasPermissions(Arrays.asList(1,2), "b")permissions将更新为包含

钥匙 价值
1 [一、二]
2 [b]

导致后续调用hasPermissions(Arrays.asList(1), "b")返回 true。

此外,每次进一步调用都会hasPermissions(Arrays.asList(1,2), "b")导致 b 再次添加:

钥匙 价值
1 [一、二、二]
2 [b]

导致该列表变得越来越长,直到内存耗尽。这个充满重复项的极长列表会减慢访问检查速度,例如hasPermissions(Arrays.asList(1), "c")爬行。

哦,顺便说一下,init第一次调用时调用的惰性初始化hasPermissions不是线程安全的,但可能被多个线程访问。您应该声明权限(如果多个线程使用不安全,volatile甚至同步),或者在静态初始值设定项中调用。initinitinit