Could you provide a standalone runnable script to reproduce the issue? BTW, the script is expected to be written in Groovy/Java.
Cheers, Daniel Sun On 2020/08/08 13:19:01, Saravanan Palanichamy <chava...@gmail.com> wrote: > Hello > > I have an extension of GroovyClassLoader that I use as follows > > a) I override loadClass to make sure I decide where to load from > b) I first call loadClass on my parent class loader to make sure the class is > not loaded there (I assert if it is. This code is not shown below) > c) I then call loadClass after turning off all script loading on > myclassloader to make sure this class is not already loaded. If it is, I just > use that > d) If I get a class not found exception, I know this class is not already > loaded and so I look up a local repository to fetch a string based script and > call parseClass (I do all of this in the context of loadClass) > > This used to work with 2.5.x but when I upgrade to 3.0.5, it sits in a > blocked state (not sure if it is blocked on some mutex because of a recursion > some where). When I use my debugger , when it gets to this state, I am not > able to read any of my variable values in the debugger (which seems to > indicate some threading read lock somewhere) > > Question :- Am I doing this the right way? Why does it block and not load the > class? It locks up in the parseClass invocation (inside a validate call that > validates the sourceCode object > > My code looks like this > > class MyClassLoader constructor( > private val repository: FlowsRepository, > private val configuration: CompilerConfiguration, > parentClassLoader: ClassLoader > ) : GroovyClassLoader(parentClassLoader, configuration) { > > /** Load class [name] either from repository or class path */ > override fun loadClass( > name: String, > lookupScriptFiles: Boolean, > preferClassOverScript: Boolean, > resolve: Boolean > ): Class<*> { > return try { > // Never try to load from script files, always parse from > repository > super.loadClass(name, false, true, resolve) > } catch (e: ClassNotFoundException) { > // Try fetching it from the repository > parseFromRepository(name) > } > } > > /** Parse [name] from the flow repository and cache it */ > private fun parseFromRepository(name: String): Class<*> { > > // Fetch flow source > val flow = repository.fetchFlow(name) ?: throw > ClassNotFoundException("Unable to find flow $name") > > // Parse the class if found > try { > // If parseClass yields a class whose name does not match > (typically when we are trying to find an inner > // class (A.B) by parsing the outer class source file (A.groovy), > throw class not found. The compiler will > // attempt to then find A$B which is how inner classes are stored > in the class loader. This find will > // succeed (this process is repeated for inner classes inside > inner classes) > super.parseClass(flow.sourceCode, true) > > // The class parsed may not be the class you are looking for, but > it may be an inner class, so > // use the cache to get it > return getClassCacheEntry(name) ?: throw > ClassNotFoundException("Unable to find flow $name") > } catch (e: CompilationFailedException) { > throw CodeQualityException("Compile error", e) > } > } > } >