Re: Class loaders to use
Jochen Theodorou <[email protected]> Mon, 7 Jul 2025 12:40:03 +0200
| Newsgroups | gmane.comp.lang.groovy.user |
|---|---|
| Message-ID | <[email protected]> |
On 07.07.25 02:10, Saravanan Palanichamy wrote: > Hello Groovy users >=20 > I am looking for help in setting up my class loaders with the Groovy=20 > compiler. This is my understanding so far >=20 > 1. The compiler is an external tool to compile (Groovy is a java based > compiler) and therefore it must have its own class paths and a class > loader to load libraries it needs (the COMPILER class loader). This > includes the transform loaders needed for static compilation etc > 2. The compiled code has its own set of class paths and there must have > a separate class loader (the CLASSPATH class loader) > 3. The two should be completely separate (I think) the Groovy compiler is not based on the java compiler. And both=20 compilers can be used internally and externally. Unless I misunderstand=20 what you mean with "external tool". It does need a class loader, because that is used to find classes during= =20 compilation. If you for example compile "class X extends Foo", then Foo=20 needs to be found. For example the compiler has to check if the class is= =20 final, if it has abstract methods and many more things. The transform loader is needed for compilation regardless of static or=20 not. those transforms consists of a front class in form of an annotation= =20 and a backing class, with the actual implementation. The front class=20 must be visible in the normal class loader to find classes, the=20 implementing class must be visible by the transform loader. Both loaders= =20 must have a parent knowing the same groovy library, or be that loader=20 itself. The compiler will then use the transform loader to load and=20 execute the transform. > However, the compiler sometimes will add class nodes as part of AST=20 > transformations (Class nodes created with ClassHelper.create) ... In=20 > that case, which class loader should be used for creating these class=20 > nodes? Or does it not matter (I think it matters because I may use a=20 > different version of jar in the compiler vs the compiled code) Let me try some ascii art > G > / \ > D T So D and T have as parent G These loaders could be all one loader long as it is a GroovyClassLoader,= =20 because that is what the compiler requires. D is the defining class loader for classes produced by the compiler. D=20 is really only used if there is no target directory given I think. the=20 FileSystemCompiler for example compiles to the file system, not to in=20 memory classloaders. GroovyShell on the other hand typically does not=20 compile to the file system. G is the class loader used by the compiler to find classes. The compiler= =20 thus sees all classes visible to G. In the FileSystemCompiler we tend to= =20 make one classloader for G load all those classes from the classpath,=20 but of course G can have parents as well. G is the loader containing the= =20 Groovy library itself, including the compiler and all helper classes of=20 the normal compiler. T is the transform loader, that can be used extra to load transforms. T=20 needs to use the same Groovy lib, the facade of the transform must be in= =20 C, otherwise the compiler cannot find it and the implementing code in T. A usual scenario is to do > GT > | > D meaning G and T are the same loader. GroovyClassLoader, if used for=20 compilation as well uses for example an inner loader for D, allowing=20 recompilation of classes to some extend. Anyway... as I said you can merge the loader with the parent in my=20 structure and still get a valid setup for class loading if you want to=20 do it like that. > If I have to use the CLASSPATH class loader for creating class nodes,=20 > are there standard patterns to help do this (given that=20 > ClassHelper.create is a static method)? You mean classes nodes for preexisting classes, which we do not compile.= =20 You mean ClassHelper.make, which does not safe the created ClassNode. It= =20 is safe for compiling with it multiple times, just do not the=20 "withCaching" methods. there is actually one more variant of class loaders you can use. Have=20 the Groovy library as parent and then a class loader that contains your=20 classes you want to compile against as child. D would be then be a child= =20 of this. T can be a child of G, if you need not to load any of those=20 classes you compile against in T, or if you do a child of that loader. But maybe you describe a bit the structure you want to have Groovy=20 itself and for the classes you compile against and if you really want T=20 to be separate. bye Jochen