> 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?

That is the key question. The simplest answer is, "Yes, all of those." We
can get some info about class loading activity from native JVM events in
the flight recorder, but in our apps there are a lot of other things at
play. Being able to isolate out Groovy and analyze it alongside the flight
recorder events we've implemented is important.

> If you want to monitor the compilation, then maybe you should go a step
deeper. GroovyScriptEngine is only a frontend to the compiler.

Going that step deeper is exactly what we'd like: we just want to be able
to do it *and* use the GroovyScriptEngine. To get specific, in our
proof-of-concept we are using the
CompilationUnit#addPhaseOperation(IGroovyClassOperation) method to add an
event for class output. We overrode GroovyClassLoader#parseClass to add an
event for class parsing. The trouble we hit is that even though we supply
our subclass of the GroovyClassLoader to our GroovyScriptEngine at
construction time, our override to parseClass effectively gets ignored by
GroovyScriptEngine.ScriptClassLoader's implementation, which doesn't
delegate to our supplied classloader. While we want all the caching
benefits of ScriptClassLoader#parseClass, we'd also like the behaviour we
add to the GroovyClassLoader we pass in to be honored.

While we certainly can just copy and paste the source of GroovyScriptEngine
into our app and make GroovyScriptEngine.ScriptClassLoader subclass it,
that seemed more like a workaround where a contribution would have done
better.

In short, I'm 100% on board with getting deeper into Groovy in order to
monitor compilation events. What I'd like is if GroovyScriptEngine could be
made to honor that customization in how it instantiates ScriptClassLoader.
I realize there's probably a *lot* of Hyrum's Law
<https://www.hyrumslaw.com/> risk here. That's part of why I thought I'd go
to the mailing list for ideas from folks deeply familiar with the
architecture.

To put it most simply, what is the lowest risk way to use
GroovyScriptEngine while still being able to modify the behaviour of
GroovyClassLoader, for the purposes of getting events into Java Flight
Recorder?

Thanks,

Jonny


On Fri, Feb 14, 2025 at 4:05 AM Jochen Theodorou <blackd...@gmx.org> wrote:

>
>
> 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
>

Reply via email to