// Idea: Every class loader makes only a single class so they can be // garbage collected more easily. srecord noeq LASMultiClassLoader(ClassLoader parent) is ILASClassLoader, AutoCloseable { settable bool rememberClassBytes; new WeakValueMap definedClasses; Lock lock = lock(); event classDefined(Class c); *(Class parent) { this(parent.getClassLoader()); } { definedClasses.onValueForKeyReleased(key -> printWithMS(":: CLASS UNLOADED :: " + key)); } selfType runnablesReferenceQueue(RunnablesReferenceQueue queue) { definedClasses.queue(queue); this; } int nClassesLoaded() { ret l(definedClasses); } Cl definedClasses() { ret values(definedClasses.snapshot()); } public Class defineLASClass(S name, IF0 generateClass) { lock lock; try object definedClasses.get(name); var cl = new IndividualClassLoader().rememberClassBytes(rememberClassBytes); print("Generating class " + name); Class c = cl.defineAClass(name, generateClass!); definedClasses.put(name, c); classDefined(c); ret c; } close { dispose definedClasses; } class IndividualClassLoader extends InMemoryClassLoader { *() { super(parent); } // Allows one script-defined class to see another one protected Class findClass(S name) throws ClassNotFoundException { try object definedClasses.get(name); ret super.findClass(name); } } }