0

i've loaded jar dynamically from other jar file, then at some point, i want to delete this jar and replace it by newer version, on linux it works fine, while on windows when i try to move the file to backup directory i get file being used by another process exception.

public void loadJarAndClass() {
    URL[] jarUrl = new URL[1];
    jarUrl[0] = jarFile.toURI().toURL();
     classLoader = new URLClassLoader (jarUrl, this.getClass().getClassLoader());
     classToLoad = Class.forName ("Burner.MainWindow", true, classLoader);

}

public void unloadJarAndClass() {
        /* all object must be collected in order to reload jar */
        jarFile = null;
        dukeClassLoader = null;
        classToLoad = null;
        System.gc();

    }

my main:

jarPath = currentPath.getAbsolutePath() + File.separator + JAR_NAME;
jarFile = new File(jarPath);
loadJarAndClass();
unloadJarAndClass();
Files.delete(FileSystems.getDefault().getPath(jarPath));

my problem is with the delete which throws exception " the process cannot access the file because it is being used by another process"

how can i bypass this exception and close any handler opened ?

shd
  • 1,201
  • 4
  • 17
  • 29
  • [this link](http://stackoverflow.com/questions/7487952/how-do-i-close-a-classloader) could be helpful. You seem to have a strong reference somewhere pointing to some resources of your dynamically loaded JAR file. On windows this might prevent properly closing the JAR and therefore won't allow for re/moval of the JAR file itself – Roman Vottner Jun 22 '15 at 12:13

2 Answers2

0

Try using Classloader.close() method,

Here is the extract from the Oracle link,

In Java SE 7, the URLClassLoader close() method effectively invalidates the loader, so that no new classes can be loaded from it. It also closes any JAR files that were opened by the loader. This allows the application to delete or replace these files and, if necessary, create new loaders using new implementations.

Following is the simplified version of the code that might serve the purpose,

public class Example {

    public static void main(String[] args) throws IOException, ClassNotFoundException {
        String jarPath = "C:\\example.jar";
        File jarFile = new File(jarPath);   
        URL[] jarUrl = new URL[1];
        jarUrl[0] = jarFile.toURI().toURL();
        URLClassLoader classLoader = new URLClassLoader (jarUrl, Example.class.getClassLoader());
        Class classToLoad = Class.forName ("DataGenerator", true, classLoader);
        classLoader.close();
        Files.delete(FileSystems.getDefault().getPath(jarPath)); 
    }
}
Sathish
  • 4,975
  • 3
  • 18
  • 23
  • @shd, i have updated the answer with a Example test where i'm able to successfully delete the jar file on Windows. FYI. I could not delete the jar file if the close() method is not called, but able to delete it when close() method is called on the URLClassLoader. Also, i've tried this on JDK8 – Sathish Jun 22 '15 at 12:21
0

please try closing the classloader before you 'unload' it.

public void unloadJarAndClass() throws IOException {
        dukeClassLoader.close();

        /* all object must be collected in order to reload jar */
        jarFile = null;
        dukeClassLoader = null;
        classToLoad = null;
        // System.gc(); don't do this unless you're really 
        // sure you have to !
    }

I would recommend not calling System.gc() explicitly ! (see Why is it bad practice to call System.gc()? for example)

Community
  • 1
  • 1
André R.
  • 1,627
  • 10
  • 14