Почему у моего кода утечка памяти после многих вызовов функций? Является ли ClassLoader проблемой? - PullRequest
1 голос
/ 03 мая 2020

У меня есть метод getAllTests (), который загружает внешний jar-файл в папку и с помощью метода поиска Reflection с Annotation Test (@Test). Я использую:

URLClassLoader класс для загрузки Jar File;

Class currentClass=child.loadClass(classname); для класса загрузки;

Method method = currentClass.getMethods()[i];

Annotation annTest = method.getAnnotation(Test.class);

для получения метода и получения аннотации.

Мой код такой:

public static void getAllTests() throws IllegalArgumentException,  NoSuchMethodException, InvocationTargetException, IllegalAccessException, IOException,LinkageError, ClassNotFoundException {
        TestLoaderApplication.testClassObjMap.clear(); <--is a HashMap class
        LoadLibrary loadLibrary=new LoadLibrary();<--used for search all file .jar in folder
        List<JarFile> jarList= loadLibrary.getListJar(pathJars).stream().map(f -> {
            try {
                return new JarFile(f);
            } catch (IOException e) {
                e.printStackTrace();
            }
            return null;
        })
                .collect(Collectors.toList());

        for (JarFile j : jarList) {
            URLClassLoader child = new URLClassLoader(
                    new URL[] {new File(j.getName()).toURI().toURL()},
                    ServiceUtil.class.getClassLoader()
            );

            for (Enumeration<JarEntry> entries = j.entries(); entries.hasMoreElements(); ) {
                JarEntry entry = entries.nextElement();
                String file = entry.getName();
                if (file.endsWith(".class")) {
                    String classname = file.replaceAll("/", ".")
                            .substring(0, file.lastIndexOf("."));
                    try {

                        Class currentClass=child.loadClass(classname);
                        List<String> testMethods = new ArrayList<>();
                        for (int i = 0; i < currentClass.getMethods().length; i++) {
                            Method method = currentClass.getMethods()[i];
                            Annotation annTest = method.getAnnotation(Test.class);
                            Annotation annTestFactory = method.getAnnotation(TestFactory.class);
                            if (annTest != null || annTestFactory != null) {
                                testMethods.add(method.getName());
                            }
                        }//fine for metodi
                        if (testMethods.size() >=1) {
                            testClassObjMap.put(j.getName().substring(j.getName().lastIndexOf("\\")+1),classname,testMethods);
                            TestLoaderApplication.testClassObjMap.put(j.getName().substring(j.getName().lastIndexOf("/")+1),classname,testMethods);
                            LOGGER.info(String.format("%s %s %s",j.toString(),classname,testMethods));
                        }
                    }catch (NoClassDefFoundError e) {
                        LOGGER.warn("WARNING: failed NoClassDefFoundError " + classname + " from " + file);
                    }
                    catch (Throwable e) {
                        LOGGER.warn("WARNING: failed to instantiate " + classname + " from " + file);
                    }

                }//if .class

            }//chiudo jarentry for
            j.close();
            child.close();
            child=null;
        }//chiudo jarfile for
        System.gc();
        LOGGER.info("Test Loader Console Back-End:\tFine Reflection Scan");

    }

В конце этой функции я закрываю JarFile (j) и classLoader (child) и set child = null и agter вызывают сборщик мусора. Но если я вызову этот метод много раз в конце, у меня будет около 100% памяти, используемой java веб-приложениями.

Этот метод используется в проекте начальной загрузки, и я использую Tomcat для веб-сервера.

* 1023 Можете ли вы порекомендовать некоторую оптимизацию при использовании classLoader, и если это правильный способ поиска методов с аннотацией @Test в Java? Спасибо
...