Может ли загруженный JAR быть удален Java-процессом?


Здравствуйте у меня есть следующая проблема:

В процессе удаления я загружаю JAR (JDBC-драйвер).

    URL pDriverJar = jarToDelete.toURI().toURL();
    URL[] lURLList = new URL[]{pDriverJar};
    URLClassLoader lLoader =  new URLClassLoader(lURLList, Thread.currentThread().getContextClassLoader());
    Thread.currentThread().setContextClassLoader(lLoader);
    Class<?> aClass = Class.forName("jdbc.Driver"); // was Oracle: oracle.jdbc.OracleDriver but should not be important

    if(jarToDelete.delete()){
        System.out.println("deleted");
    }else {
        jarToDelete.deleteOnExit();
    }

После завершения JVM, jar все еще существует.

В качестве рабочей области я создал tempfile и скопировал Jar в этот tempfile. Но теперь Tempfile не будет удален.

Я читал, что если ClassLoad-GC, то загруженные банки могут быть удалены.

У кого-нибудь есть идея, как удалить этот файл?

2 3

2 ответа:

Это зависит от операционной системы. Windows не позволит вам удалять файлы, которые используются, но Linux будет.

Одним из решений было бы запустить второй процесс, который ждет, пока ваш JVM умрет, а затем удаляет файл, так как даже если вы очистите все ссылки на загрузчики классов, использующие его, нет никакой гарантии, что они выпустят файл. Не существует способа принудительной сборки мусора (или даже завершения) объекта.

Другим решением было бы написать загрузчик классов, который загружает банку. Таким образом, когда вы хотите избавиться от него, вы можете быть уверены, что банка закрыта. Если единственным объектом, открывшим его, был ваш загрузчик классов, то вы можете быть уверены, что он свободен и должен быть удален.

Эта проблема была исправлена в Java 7; Используйте метод close() в классе ClassLoader. Для более старых версий существует несколько вариантов:

  • Напишите пользовательский загрузчик классов, например , как это

  • Используйте отражение и закройте все экземпляры JarFile; они находятся в sun.misc.URLClassPath