I am not following every detail here, but as long as you have a variable and/or an indy state that gives access to any part of a dynamically loaded class, then that class will not be unloaded. There’s no way to unload most of a class but keep one of its methods, for example. And if the class is live, its class loader will be live as well.
So, indy or field -> MH or VH -> class -> loader is the chain that keeps everything alive. On 23 Aug 2023, at 1:09, Jochen Theodorou wrote: > Am 22.08.23 um 22:38 schrieb Charles Oliver Nutter: >> On Tue, Aug 22, 2023 at 3:07 PM Jochen Theodorou <[email protected]> wrote: >>> Is there any possible circumstance in which the class Foo can now be >>> garbage collected? My assumption is no. >> >> I can't speak to varhandles but this is very much like how JRuby >> handles all of our jitted Ruby methods and indy binding. Under normal >> circumstances, most Ruby methods get jit-compiled to bytecode lazily >> and loaded into a unique classloader each; that classloader is not >> rooted anywhere, so that if the Ruby method goes away, the jitted >> class can also go away. > > But don't you get problems with the method going away and then being > required again? > >> If the method was transient in the Ruby world (e.g. created on a >> "singleton" object that goes out of scope) but is still bound at a >> call site, it will not get garbage collected. We've actually had some >> "won't fix" bug reports about indy call sites rooting methods or >> classes that were called once (as is our expectation, not a bug). > > I can maybe actually make my description more clear with an example in > pseudo Java: > > ''' > class ScriptRunner { > public runScript10times(String script) { > Object instance = compileJava(script) > for (int i=0; i<10; i++) { > instance.getClass().getMethod("run").invoke(instance) > } > } > } > ''' > > where compileJava will compile the script into bytecode and load it > under the assumption that it is a run() method. The script could be > normal Java. Then compileJava would maybe leverage javac for this and a > bit of reflection and a classloader that is only for that class to be > defined in. Let us assume ScriptRunner will stay around for a long time > and the classloader used is not referenced anywhere. > > Anyway... my assumption for Java would be now, that after the method > call is done: > * instance can be collected and is in fact pretty fast. > * since instance and classloader are not referenced, the script class is > becoming collectable > * the script class can be collected once GC gets to it. > > Now let us assume ScriptRunner is almost Java, everything is the same, > but the call to run() > "instance.getClass().getMethod("run").invoke(instance)" is now done > using invokedynamic "instance.run()". Let us assume there will be a > runtime selection of the run method, that does something like the > pseudo-Java version, unreflects the method and invokes the handle as > well as installs it in the mutable callsite as target (with guards to > detect a new script class). > > Then it seems to me like: > * instance can be collected like above > * the class will be hard/strong referenced by the MethodHandle instance > type information in the callsite > * the script class can be collected only once the callsite target is > rewritten or the class ScriptRunner goes away. > > Am I wrong? > > > bye Jochen > _______________________________________________ > mlvm-dev mailing list > [email protected] > https://mail.openjdk.org/mailman/listinfo/mlvm-dev _______________________________________________ mlvm-dev mailing list [email protected] https://mail.openjdk.org/mailman/listinfo/mlvm-dev
