Reputation: 83
I'm using a GroovyClassLoader to load multiple groovy files (not scripts) that have Class names and package structures. I believe I'm running into an issue of multiple Class files being loaded for the same Class, despite calling parseClass only once per file based on this type of error message:
org.codehaus.groovy.runtime.typehandling.GroovyCastException: Cannot cast object 'TickIt.Pizza@3eea9be9' with class 'TickIt.Pizza' to class 'TickIt.Pizza'
Additionally, I have some instances where I use a Static setter for storing a variable, and calling the Class implicitly seems to indicate there are additional copies of the Class since after setting the variable I can reference it and it seems to be empty.
I've made a small test to attempt to prove the problem, and it seems to indicate that indeed there are multiple Classes loaded. By finding the matching Class in loadedClasses on my GroovyClassLoader, I can compare to the implicit Class. For my DockingBay Class, I have a static Map called shuttles. The loaded class of DockingBay has value, but implicitly calling Dockingbay.shuttles comes up empty. See below:
DockingBay: ${ DockingBay.classLoader } <br>
${ DockingBay.shuttles } <br>
Loaded: ${ PartsStore.groovyClassLoader.loadedClasses[28].classLoader } <br>
${ PartsStore.groovyClassLoader.loadedClasses[28].shuttles }<br>
Are they the same?: ${ PartsStore.groovyClassLoader.loadedClasses.contains(DockingBay) }
Output:
DockingBay: groovy.lang.GroovyClassLoader$InnerLoader@6bc407fd
[:]
Loaded: groovy.lang.GroovyClassLoader$InnerLoader@4b79ac84
[class hudelements.HudElements:hudelements.HudElements@4f936da8, class TickIt.PizzaShop:TickIt.PizzaShop@e041f0c, class calc.Calc:calc.Calc@6a175569, class monitor.Monitor:monitor.Monitor@69c79f09]
Are they the same?: false
Here's my code that loads my files to the GroovyClassLoader, which I call PartsStore.
boolean hasLoaded = false
GroovyClassLoader groovyClassLoader
loadedClasses = []
public scan() {
if (hasLoaded) {
println('Purging groovyClassLoader Meta.')
for (def clazz in groovyClassLoader.loadedClasses)
GroovySystem.getMetaClassRegistry().removeMetaClass(clazz)
println('Clearing groovyClassLoader Cache.')
groovyClassLoader.clearCache()
} else {
println('Creating new groovyClassLoader.')
groovyClassLoader = new GroovyClassLoader(Spaceport.class)
}
hasLoaded = true
for (String path in Spaceport.config.modules.'class paths') {
File dir = new File(path)
groovyClassLoader.addClasspath(dir.getAbsolutePath())
}
def errors = false
for (String path in Spaceport.config.modules.'include paths') {
// Get directory listing
println('+ -> ' + path)
File[] directoryListing = FileUtils.listFiles(new File(path), null, false)
// Load all .groovy files
if (directoryListing != null) {
for (File child : directoryListing) {
if (FilenameUtils.getExtension(child.getName()) == 'groovy') {
try {
println 'Loading include "' + child + '"'
groovyClassLoader.parseClass(child))
} catch (Exception e) {
errors = true
e.printStackTrace()
}
}
}
}
}
}
I would expect no matter where I call my class DockingBay from (provided it's loaded on the same GroovyClassLoader), I would receive the same Class that is loaded in the ClassLoader. It seems I am not. I noticed that comparing the classLoaders of the Classes shows they are different (but consistent) InnerLoaders. Why?
Upvotes: 1
Views: 1182