On 2/11/25 23:13, Jonathan Carter wrote:
My team and I are trying to instrument JFR to monitor some of the deeper activity of Groovy compilation in an app which runs Groovy Scripts. We're trying to get a picture of what's going on when users have certain hard-to-reproduce performance problems.
JFR = Java Flight Recorder
We setup a subclass of GroovyClassLoader that overrode createCompilationUnit and parseClass, firing off some JFR events when those methods get called. We're hitting a wall with the groovy.util.GroovyScriptEngine.ScriptClassLoader private class. While that provides a bunch of useful cacheing, it doesn't delegate to the parent classloader for createCompilationUnit or parseClass. Instead, it calls to super. I expect (though I don't know) that this is expected behaviour for a Java classloader, and that a parent should only get called when the child needs it.
In the JVM a class identity is determined by name and class loader. A Classloader is supposed to return the same class each time. And a Classloader is suppose to ask the parent first for a class. But this is not normal class loading. This is on-demand compilation with optional recompilation. And I think we violate in that about all of those principles. Better not expect it to behave like a regular class loader.
While I could create my own copy of groovy.util.GroovyScriptEngine and manipulate the behavior there, my hunch is that there should be some more maintainable way to monitor Groovy compilation. Some of them would want to push some patches upstream to Groovy, perhaps there are some that wouldn't require that.
If you want to monitor the compilation, then maybe you should go a step deeper. GroovyScriptEngine is only a frontend to the compiler.
So, fellow Groovy devs, which of the following seems like the most sensible path to meet the felt need of monitoring Groovy compilation? 1. Adding some native JFR events to Groovy. This would necessarily target the Groovy 5+ line, since JFR is only freely available on OpenJDK 11+. 2. Modifying how groovy.util.GroovyScriptEngine.ScriptClassLoader is declared or used so that it could be overridden, in part or in whole? 3. Some third option born from a better mind than mine? :) Please feel free to tell me if I'm missing something obvious, by the way. It is probable!
maybe first we should define what activities you want to monitor. Is it when a compilation is started/finished, is it class loading activity, is it lookups on the file system, .... all of that? bye Jochen