<div dir="ltr">Do you need the classloader to be able to load new classes after the checkpoint is restored?  If not, there's a "close()" method on URLClassLoader that should close the jar and file URLs and "makes a best effort attempt to close all opened files".<div><br></div><div>Obviously not a complete solution but it may work around your issue for now.</div><div><br></div><div>--Dan</div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Fri, Dec 2, 2022 at 2:30 PM Nikola Grcevski <<a href="mailto:grcevski@gmail.com">grcevski@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">Hello crac-dev,<br>
<br>
While experimenting more with CRaC and Elasticsearch I encountered one<br>
more issue and I thought I should bring it up for discussion.<br>
<br>
We load some JARs dynamically and these don't get marked as 'persistent'.<br>
<br>
For example:<br>
<br>
final ClassLoader classLoader = buildClassLoader();<br>
try {<br>
   final Class<? extends Supplier<?>> cls = (Class<? extends<br>
Supplier<?>>)classLoader.loadClass("org.elasticsearch.io.ansi.AnsiConsoleLoader");<br>
...<br>
} catch (ReflectiveOperationException e) {<br>
   throw new RuntimeException("Failed to load ANSI console", e);<br>
}<br>
<br>
private static ClassLoader buildClassLoader() {<br>
   final Path libDir = Path.of(".").resolve("lib").resolve("ansi-console");<br>
<br>
   try {<br>
      final URL[] urls = Files.list(libDir)<br>
                                  .filter(each -><br>
each.getFileName().toString().endsWith(".jar"))<br>
                                   .map(SimpleModule::pathToURL)<br>
                                   .toArray(URL[]::new);<br>
<br>
       return URLClassLoader.newInstance(urls,<br>
SimpleModule.class.getClassLoader());<br>
    } catch (IOException e) {<br>
       throw new RuntimeException("Failed to list jars in [" + libDir<br>
+ "]: " + e.getMessage(), e);<br>
    }<br>
}<br>
<br>
I think typically we'd say that these should be closed and recreated<br>
on snapshot and restore,<br>
but it's not easy to do with ClassLoaders. I think we'd need to lose<br>
the reference and have<br>
GC collect the class loader for all the files to close.<br>
<br>
I was able to work around this issue by putting all the jars we might<br>
load dynamically<br>
on the class path with -cp.<br>
<br>
I'm wondering if the work around is the correct 'fix' or is there something<br>
else that should be done? If the URLs are files, I suppose we can mark those as<br>
persistent?<br>
<br>
I made a GitHub repo with all the code that shows the issue here:<br>
<a href="https://github.com/grcevski/openjdk_CRaC_simplemodule" rel="noreferrer" target="_blank">https://github.com/grcevski/openjdk_CRaC_simplemodule</a><br>
<br>
Thanks,<br>
Nikola<br>
<br>
</blockquote></div>