static class JavaXClassLoader extends URLClassLoader { S progID; Set files = syncLinkedHashSet(); Set triedToLoad = synchroSet(); Set loadedClasses = synchroSet(); bool retired; O retiredMarker; IF1 findClass_extension; S mainClassName; bool verbose; *(S progID, L files) { this(progID, files, getSystemClassLoader()); } *(S progID, L files, ClassLoader parent) { super(new URL[0], parent, vm_globalACC()); this.progID = progID; fOr (File f : files) addFile(f); } Class super_findClass(S name) throws ClassNotFoundException { ret super.findClass(name); } protected Class findClass(S name) throws ClassNotFoundException { if (verbose) System.out.println(this + " findClass: " + name); if (findClass_extension != null) { Class c = findClass_extension.get(name); if (verbose) System.out.println("extension returned: " + c); if (c != null) ret c; } bool triedBefore = !triedToLoad.add(name); try { Class c = super.findClass(name); if (verbose) System.out.println("super.findClass returned: " + c); loadedClasses.add(c); if (eq(name, mainClassName())) callOpt(javax(), 'registerAMainClass, c); ret c; } catch (ClassNotFoundException e) { if (verbose) System.out.println(getStackTrace(e)); throw new ClassNotFoundException("Class " + name + " not found in " + joinWithComma(map(f f2s, files)) + " (progID=" + progID + ")" + (triedBefore ? ", tried to load before" : ""), e); } } toString { ret shortClassName(this) + "[" + systemHashCodeHex(this) + "] - " + progID; } S mainClassName() { if (mainClassName == null) mainClassName = or2(trim(loadTextFileResource(this, "main-class")), "main"); ret mainClassName; } bool addFile(File f) ctex { if (!files.add(f)) false; addURL(f.toURI().toURL()); mainClassName(); // calculate early. no good loading text files later true; } }