<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=Windows-1252">
</head>
<body>
<div>
<div>
<div dir="ltr">Thanks Dan, I’ll give that a shot. We’ll need the classloader after restore, but I can recreate it.</div>
</div>
<div id="ms-outlook-mobile-signature">
<div></div>
</div>
</div>
<hr style="display:inline-block;width:98%" tabindex="-1">
<div id="divRplyFwdMsg" dir="ltr"><font face="Calibri, sans-serif" style="font-size:11pt" color="#000000"><b>From:</b> Dan Heidinga <heidinga@redhat.com><br>
<b>Sent:</b> Friday, December 2, 2022 2:53:20 PM<br>
<b>To:</b> Nikola Grcevski <grcevski@gmail.com><br>
<b>Cc:</b> crac-dev@openjdk.org <crac-dev@openjdk.org><br>
<b>Subject:</b> Re: Creating snapshots with dynamically loaded JARs</font>
<div> </div>
</div>
<div>
<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="x_gmail_quote">
<div dir="ltr" class="x_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="x_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>
</div>
</body>
</html>