title: Unloaded Jar still in use by Process ( Failed to Delete or Replace jar)
body: <pre><code>package com.kovair.omnibus.adapter.platform;
  
  import java.io.BufferedReader;
  import java.io.File;
  import java.io.InputStreamReader;
  import java.net.URL;
  import java.net.URLClassLoader;
  import java.nio.file.Files;
  import java.nio.file.Paths;
  import java.util.ArrayList;
  import java.util.Hashtable;
  import java.util.List;
  import java.util.Set;
  import java.util.jar.JarEntry;
  import java.util.jar.JarFile;
  
  import com.kovair.omnibus.adapter.platform.core.IService;
  import com.kovair.omnibus.adapter.platform.core.util.AdapterLoaderInfo;
  import com.kovair.omnibus.adapter.platform.manager.AdapterUtility;
  import com.kovair.omnibus.adapter.platform.manager.KovairLogManager;
  
  public class AdapterLoader {
  
      private static Hashtable&lt;String,URLClassLoader&gt; AdapterClassLoaderList = null;
      public static Hashtable&lt;String, IService&gt; AdapterList;
      private static final String Config = &quot;config.cfg&quot;;
      
      
      public static void LoadAdapterRunTime(File tempDir) {
          try {
              System.out.println(&quot;LoadAdapterRunTime Starts.&quot;);
  
              List&lt;AdapterLoaderInfo&gt; tempAdapterObjectList = InitializeAdapterFromDirectoryExt(tempDir, false);
  
  
              if (tempAdapterObjectList != null &amp;&amp; tempAdapterObjectList.size() &gt; 0 ) {
                  if (AdapterList == null) {
                      AdapterList = new Hashtable&lt;String, IService&gt;(); //IService is user defined Interface
                  }
                  
                  for(AdapterLoaderInfo tempAdapterObject : tempAdapterObjectList)
                  {
                      if(tempAdapterObject.AdapterObject != null &amp;&amp; tempAdapterObject.AdapterInfo != null &amp;&amp; !AdapterList.containsKey(tempAdapterObject.AdapterIdentifier))
                      {
                          AdapterList.put(tempAdapterObject.AdapterIdentifier, tempAdapterObject.AdapterObject);
                      }
                  }
              }
              
          } catch (Exception ex) {
              System.out.println(&quot;Error Message - &quot; + ex.getMessage() + &quot;.. Stacktrace - &quot;
                      + ex.getStackTrace());
              ex.printStackTrace();
          }
          finally
          {
              System.out.println(&quot;AdapterLoader : Method : LoadAdapterRunTime Ends.&quot;);
          }
      }
      
      
      public static void ReleaseAdapters() throws Exception {
          try {
              System.out.println(&quot;ReleaseAdapters Starts.&quot;);
              
              if(AdapterClassLoaderList != null &amp;&amp; AdapterClassLoaderList.size() &gt; 0)
              {
                  
                  // getting keySet() into Set
                  Set&lt;String&gt; setOfAdapters = AdapterClassLoaderList.keySet();
           
                  // for-each loop
                  for(String key : setOfAdapters) {
                      
                      AdapterClassLoaderList.get(key).close();
                  }
                  
                  AdapterClassLoaderList.clear();
                  AdapterClassLoaderList = null;
                  AdapterList.clear();
                  AdapterList = null;
              }
              
          } catch (Exception ex) {
              System.out.println(&quot;Error Message &quot; + ex.getMessage() + &quot;.. Stacktrace - &quot;
                      + ex.getStackTrace());
              throw ex;
          }
          finally {
              System.out.println(&quot;ReleaseAdapters Ends.&quot;);
          }
      }
      
      
      
      public static List&lt;AdapterLoaderInfo&gt; InitializeAdapterFromDirectoryExt(File AdapterDirectory, boolean tempLoad) {
          AdapterLoaderInfo AdapterLoaderInfo = null;
          Hashtable&lt;String, String&gt; configInsideJar = new Hashtable&lt;String, String&gt;();
          File jarFile = null;
          File versionSpecificAdapter = null;
          List&lt;AdapterLoaderInfo&gt; adapterLoaderInfoList = new ArrayList&lt;AdapterLoaderInfo&gt;();
          try {
              System.out.println(&quot;AdapterLoader : Method : InitializeAdapterFromDirectory Started.&quot;);
              //// ------------Getting the Jar file pointer---------------------------------
              try {
                  if (AdapterDirectory != null &amp;&amp; AdapterDirectory.exists()) {
                      System.out.println(&quot;InitializeAdapterFromDirectory : Adapter Initialization. Loading Adapter Name - &quot; + AdapterDirectory.getName());
                      
  
                      File[] AdapterAllVersions = AdapterDirectory.listFiles();
                      
                      if (AdapterAllVersions != null &amp;&amp; AdapterAllVersions.length &gt; 0) 
                      {                       
                          System.out.println(&quot;InitializeAdapterFromDirectory : AdapterAllVersions.length - &quot; + AdapterAllVersions.length);
                          
                          
                          for (int j = 0; j &lt; AdapterAllVersions.length; j++) 
                          {
                              if (AdapterAllVersions[j].isDirectory() &amp;&amp; !AdapterAllVersions[j].getName().equalsIgnoreCase(&quot;temp&quot;)) 
                              {                               
                                  jarFile = null;     
                                  versionSpecificAdapter = null;
                                  
                                  
                                  versionSpecificAdapter =  AdapterAllVersions[j].listFiles()[0]; 
                                  
                                  if(versionSpecificAdapter != null &amp;&amp; versionSpecificAdapter.isDirectory())
                                  {
                                      File[] AdapterRootDirectoryContents = versionSpecificAdapter.listFiles();
                                      
                                      if (AdapterRootDirectoryContents != null &amp;&amp; AdapterRootDirectoryContents.length &gt; 0) 
                                      {                                       
                                          System.out.println(&quot;InitializeAdapterFromDirectory : AdapterRootDirectoryContents.length - &quot; + AdapterRootDirectoryContents.length);
                                          
                                          
                                          for (int i = 0; i &lt; AdapterRootDirectoryContents.length; i++) 
                                          {
                                              jarFile = null;
                                              
                                              if (AdapterRootDirectoryContents[i].isFile() &amp;&amp; AdapterRootDirectoryContents[i].getName().endsWith(&quot;.jar&quot;)) 
                                              {
                                                  System.out.println(&quot;InitializeAdapterFromDirectory : Jar File found. Name - &quot; + AdapterRootDirectoryContents[i].getName());
                                                  
                                                  jarFile = AdapterRootDirectoryContents[i];
                                                  
                                                  if (jarFile != null) {
                                                      //// ------------Reading the Configuration file inside the Jar          
                                                      try {
                                                          System.out.println(&quot;InitializeAdapterFromDirectory : Reading the Configuration file inside the Jar Starts.&quot;);
                                                          
                                                          JarFile jfileLoader = new JarFile(jarFile);
                                                          JarEntry je = jfileLoader.getJarEntry(Config);
                                                          BufferedReader br = new BufferedReader(new InputStreamReader(jfileLoader.getInputStream(je)));
                                                          String in;
                                                          while ((in = br.readLine()) != null) {
                                                              if (in.isEmpty() || in.startsWith(&quot;#&quot;))
                                                                  continue;
                                                              final String[] split = in.split(&quot; &quot;);
                                                              
                                                              System.out.println(&quot;InitializeAdapterFromDirectory : Config Reading.. Split-0 : &quot; + split[0] + &quot; : Split-1 : &quot; + split[1]);
                                                              
                                                              
                                                              configInsideJar.put(split[0], split[1]);
                                                          }
                                                          br.close();
                                                          jfileLoader.close();
                                                          jfileLoader = null;
                                                      } catch (Exception ex) {
                                                          System.out.println(&quot;AdapterLoader : LoadAdapterRepository :: InitializeAdapterFromDirectory : Error in Adapter config initialization - &quot; + ex.getMessage() + &quot;.. Stacktrace - &quot;
                                                                  + ex.getStackTrace());
                                                          throw new Exception(&quot;Error in reading Jar - &quot; + ex.getMessage());
                                                      }
                                                      finally
                                                      {
                                                          System.out.println(&quot;InitializeAdapterFromDirectory : Reading the Configuration file inside the Jar Ends.&quot;);
                                                          
                                                      }
                                                      //
                                                      // ----------------------------------------------------------------------------------------
                                                      //
                                                      //// ------------Preparing URL Collection for Jar and its dependency
                                                      List&lt;URL&gt; urlList = new ArrayList&lt;URL&gt;();
                                                      try {
                                                          System.out.println(&quot;InitializeAdapterFromDirectory : Reading Jar Dependency Starts.&quot;);
                                                          
                                                          
                                                          System.out.println(&quot;InitializeAdapterFromDirectory : Reading Jar Dependency : Dependency File - jarFile URI - &quot; + jarFile.toURI().toURL());
                                                          
                                                          
                                                          urlList.add(jarFile.toURI().toURL());   
                                                          
                                                          System.out.println(&quot;InitializeAdapterFromDirectory : Reading Jar Dependency : Dependency File - IService URI - &quot; + IService.class.getProtectionDomain().getCodeSource().getLocation().toURI().toURL());
                                                          
                                                          
                                                          urlList.add(IService.class.getProtectionDomain().getCodeSource().getLocation().toURI().toURL());
                                                          
                                                          String dependencyDirPath = versionSpecificAdapter.getPath() + &quot;/Dependency&quot;;
                                                          
                                                          System.out.println(&quot;InitializeAdapterFromDirectory : Reading Jar Dependency : Dependency File - dependencyDirPath - &quot; + dependencyDirPath);
                                                          
                                                          
                                                          if (Files.exists(Paths.get(dependencyDirPath))) {
                                          
                                                              System.out.println(&quot;InitializeAdapterFromDirectory : Reading Jar Dependency : Dependency Directory exists.&quot;);
                                                              
                                                              
                                                              File[] dependencyFileList = (new File(dependencyDirPath)).listFiles();
                                                              if (dependencyFileList != null) {
                                                                  
                                                                  System.out.println(&quot;InitializeAdapterFromDirectory : Reading Jar Dependency : dependencyFileList.length - &quot; + dependencyFileList.length);
                                                                  
                                                                  
                                                                  for (int k = 0; k &lt; dependencyFileList.length; k++) {
                                                                      if (dependencyFileList[k].isFile() &amp;&amp; dependencyFileList[k].getName().endsWith(&quot;.jar&quot;)) {
                                                                          
                                                                          System.out.println(&quot;InitializeAdapterFromDirectory : Reading Jar Dependency : Loading dependency File Name - &quot; + dependencyFileList[k].getName() +&quot; :: Full URI - &quot; + dependencyFileList[k].toURI().toURL());
                                                                          
                                                                          
                                                                          urlList.add(dependencyFileList[k].toURI().toURL());
                                                                      }
                                                                      else
                                                                      {
                                                                          System.out.println(&quot;InitializeAdapterFromDirectory : Reading Jar Dependency : Dependency File not a Jar.&quot;);
                                                                          
                                                                      }
                                                                  }
                                                              }
                                                              else
                                                              {
                                                                  System.out.println(&quot;InitializeAdapterFromDirectory : Reading Jar Dependency : dependencyFileList is Empty.&quot;);
                                                                  
                                                              }
                                                          }
                                                          else
                                                          {
                                                              System.out.println(&quot;InitializeAdapterFromDirectory : Reading Jar Dependency : Dependency Directory does not exists.&quot;);
                                                              
  
                                                          }
                                                      } catch (Exception ex) {
                                                          System.out.println(&quot;AdapterLoader : LoadAdapterRepository :: InitializeAdapterFromDirectory : Error in Reading Jar Dependency - &quot; + ex.getMessage() + &quot;.. Stacktrace - &quot;
                                                                  + ex.getStackTrace());
                                                          throw new Exception(&quot;Error in preparing dependency - &quot; + ex.getMessage());
                                                      }
                                                      finally
                                                      {
                                                          System.out.println(&quot;InitializeAdapterFromDirectory : Reading Jar Dependency Ends.&quot;);
                                                          
                                                      }
                                                      //
                                                      // -----------------------------------------------------------------------------------------------
                                                      //
                                                      //// ------------Loading the class and Casting to Interface
                                                      try {
                                                          System.out.println(&quot;InitializeAdapterFromDirectory : Loading the class and Casting to Interface Starts.&quot;);
                                                          
                                                          
                                                          if(urlList!=null &amp;&amp; urlList.size()&gt;0)
                                                          {
                                                              System.out.println(&quot;InitializeAdapterFromDirectory : Cast To Interface - urlList.size() - &quot; + urlList.size());
                                                              
                                                              
                                                              URL[] urlArray = new URL[urlList.size()];
                                                              urlArray = urlList.toArray(urlArray);
                                                              URLClassLoader AdapterClassLoader = new URLClassLoader(urlArray, IService.class.getClassLoader());
                                                              
                                                              System.out.println(&quot;InitializeAdapterFromDirectory : Cast To Interface - Main Class Name - &quot; + configInsideJar.get(&quot;Main&quot;));
                                                              
                                                              
                                                              Class&lt;?&gt; AdapterClass = Class.forName(configInsideJar.get(&quot;Main&quot;), true, AdapterClassLoader);
  
                                                              
                                                              Object AdapterObj = AdapterClass.newInstance();
                                                              IService AdapterInterface = IService.class.cast(AdapterObj);
                                                              AdapterLoaderInfo = new AdapterLoaderInfo();
                                                              AdapterLoaderInfo.AdapterObject = AdapterInterface;
                                                              AdapterLoaderInfo.AdapterInfo = AdapterInterface.Info();
                                                              AdapterLoaderInfo.AdapterIdentifier = String.format(AdapterUtility.AdapterIdentifierFormat, AdapterLoaderInfo.AdapterInfo.getTool(),AdapterLoaderInfo.AdapterInfo.getAdapterVersion(),  AdapterLoaderInfo.AdapterInfo.getAdapterName());
                                                              
                                                              
                                                              if(tempLoad)
                                                              {
                                                                  AdapterClassLoader.close();
                                                                  AdapterClassLoader = null;
                                                              }
                                                              else
                                                              {
                                                                  AdapterClassLoaderList.put(AdapterLoaderInfo.AdapterIdentifier, AdapterClassLoader);
                                                              }
                                                              
                                                              if (AdapterList != null &amp;&amp; AdapterList.containsKey(AdapterLoaderInfo.AdapterIdentifier)) {
                                                                  AdapterLoaderInfo.ErrorMessage = &quot;Similar Adapter already exists&quot;;
                                                              }
                                                              
                                                              adapterLoaderInfoList.add(AdapterLoaderInfo);
                                                          }
                                                          else
                                                          {
                                                              System.out.println(&quot;InitializeAdapterFromDirectory : Cast To Interface - urlList.size() is Zero. Unable to process Object from Jar&quot;);
                                                              
                                                          }
                                                      } catch (Exception ex) {
                                                          System.out.println(&quot;AdapterLoader : LoadAdapterRepository :: InitializeAdapterFromDirectory : Error in creating Adapter Interface - &quot; + ex.getMessage() + &quot;.. Stacktrace - &quot;
                                                                  + ex.getStackTrace());
                                                          throw new Exception(&quot;Error in creating Adapter Interface - &quot; + ex.getMessage());
                                                      }
                                                      finally
                                                      {
                                                          System.out.println(&quot;InitializeAdapterFromDirectory : Loading the class and Casting to Interface Ends.&quot;);
                                                          
                                                      }
                                                      //
                                                      // -----------------------------------------------------------------------------------------------
                                                      //
                                                  } else {
                                                      System.out.println(&quot;InitializeAdapterFromDirectory : Jar file is null.&quot;);
                                                  }                                               
                                              }
                                          }
                                      }
                                      else
                                      {
                                          System.out.println(&quot;InitializeAdapterFromDirectory : AdapterRootDirectoryContents.length is Zero&quot;);
                                      }
                                  }                                                               
                              }
                              else 
                              {
                                  System.out.println(&quot;InitializeAdapterFromDirectory : Not a valid version directory.&quot;);                              
                              }
                          }
                      }
                      else 
                      {
                          System.out.println(&quot;Adapter Initialization failed. no version directoryfound under adapter.&quot;);
                      }
                          
                  } else {
                      KovairLogManager.KovairLog.debug(&quot;InitializeAdapterFromDirectory : AdapterRootDirectoryContents.length is Zero&quot;);
                      System.out.println(&quot;Adapter Initialization failed. Directory not found.&quot;);
                  }
              } catch (Exception ex) {
                  System.out.println(&quot;Error message - &quot; + ex.getMessage() + &quot;.. Stacktrace - &quot;
                          + ex.getStackTrace());
                  throw new Exception(&quot;Adapter file reading error - &quot; + ex.getMessage());
              }
              //
              // ----------------------------------------------------------------------------------------
              //
          } catch (Exception ex) {
              System.out.println(&quot;Error Message - &quot; + ex.getMessage() + &quot;.. Stacktrace - &quot;
                      + ex.getStackTrace());
              AdapterLoaderInfo.ErrorMessage = ex.getMessage();
  
          } finally {
              System.out.println(&quot;InitializeAdapterFromDirectory Ends.&quot;);
  
          }
          return adapterLoaderInfoList;
      }
  }
  </code></pre>
  <p>In the above code snippet I am loading a jar file with its dependencies calling <code>LoadAdapterRunTime(File tempDir)</code> method.
  At later stage when I am calling <code>ReleaseAdapters()</code> method to unload the jar files it is also executed without any error and <code>AdapterClassLoaderList</code> and <code>AdapterList</code> both appears to be cleared.
  Problem starts when I am trying to replace or delete that particular jar which is loaded earlier using <code>URLClassLoader</code> and later unloaded using <code>ReleaseAdapters()</code>. When I try to delete or replace from code or using file system it shows that the jar is still in use by other process.</p>
  <p><strong>Note:</strong> I want to delete or replace thejar after unloading without server restart. I am using Spring Tool Suite 4 with external Tomcat 9 server and Adopt Open Jdk 8</p>