99import java .net .URL ;
1010import java .net .URLClassLoader ;
1111import java .nio .ByteBuffer ;
12- import java .util .HashMap ;
1312import java .util .Map ;
1413import java .util .ServiceLoader ;
1514import java .util .Set ;
15+ import java .util .concurrent .ConcurrentHashMap ;
1616
1717public final class MangoLoader extends URLClassLoader {
1818
@@ -21,8 +21,10 @@ public final class MangoLoader extends URLClassLoader {
2121 }
2222
2323 private ClassTransformers transformers = new ClassTransformers (this );
24- private final Map <String , LoadedModule > moduleMap = new HashMap <>();
25- private final Map <String , LoadedModule > localPackageToModule = new HashMap <>();
24+ private final Map <String , LoadedModule > moduleMap = new ConcurrentHashMap <>();
25+ private final Map <String , LoadedModule > localPackageToModule = new ConcurrentHashMap <>();
26+
27+
2628
2729 public MangoLoader (URL [] urls , Set <ResolvedModule > modules , ClassLoader parent ) {
2830 super (urls , parent );
@@ -76,46 +78,39 @@ void loadModuleConfiguration() {
7678 });
7779 }
7880
81+ /**
82+ * Loads the class with the specified binary name.
83+ */
7984 @ Override
80- protected Class <?> findClass (String name ) throws ClassNotFoundException {
81- if (transformers == null || transformers .isEmpty ())
82- return super .findClass (name );
85+ protected Class <?> loadClass (String cn , boolean resolve ) throws ClassNotFoundException
86+ {
8387
84- if (transformers .containsClass (name ))
85- return transformers .getClazz (name );
88+ synchronized (getClassLoadingLock (cn )) {
89+ // check if already loaded
90+ Class <?> c = findLoadedClass (cn );
8691
87- byte [] originalBytes = getClassBytes ( name );
92+ if ( c == null ) {
8893
89- if (originalBytes == null ) {
90- throw new ClassNotFoundException ("Failed to load original class bytes for " + name );
91- }
94+ LoadedModule loadedModule = findLoadedModule (cn );
9295
93- byte [] arr = transformers .transform (name );
94- if (arr != null ) {
95- Class <?> clz = defineClass (name , arr );
96- transformers .add (name , clz );
97- return clz ;
98- }
96+ if (loadedModule != null ) {
9997
100- return super . findClass ( name );
101- }
98+ // class is in module defined to this class loader
99+ c = defineClass ( cn , loadedModule );
102100
103- private byte [] getClassBytes (String clazz ) {
104- try {
105- String className = clazz .replace ('.' , '/' );
106- String classFileName = className + ".class" ;
107-
108- try (var is = getResourceAsStream (classFileName )) {
109- if (is != null ) return is .readAllBytes ();
101+ } else {
102+ return getParent ().loadClass (cn );
103+ }
110104 }
111- } catch (IOException e ) {
112- return null ;
113- }
114- return null ;
115- }
116105
117- private Class <?> defineClass (String name , byte [] bytes ) {
118- return super .defineClass (name , bytes , 0 , bytes .length );
106+ if (c == null )
107+ throw new ClassNotFoundException (cn );
108+
109+ if (resolve )
110+ resolveClass (c );
111+
112+ return c ;
113+ }
119114 }
120115
121116 @ Override
@@ -131,6 +126,17 @@ protected URL findResource(String moduleName, String name) throws IOException {
131126 return null ;
132127 }
133128
129+ @ Override
130+ protected Class <?> findClass (String cn ) throws ClassNotFoundException {
131+ Class <?> c = null ;
132+ LoadedModule loadedModule = findLoadedModule (cn );
133+ if (loadedModule != null )
134+ c = defineClass (cn , loadedModule );
135+ if (c == null )
136+ throw new ClassNotFoundException (cn );
137+ return c ;
138+ }
139+
134140 @ Override
135141 protected Class <?> findClass (String moduleName , String name ) {
136142 Class <?> c = null ;
@@ -161,12 +167,24 @@ private Class<?> defineClass(String cn, LoadedModule loadedModule) {
161167 return null ;
162168 }
163169
164- try {
165- return defineClass (cn , bb , loadedModule .getCodeSource ());
166- } finally {
167- reader .release (bb );
168- }
170+ if (transformers .containsClass (cn ))
171+ return transformers .getClazz (cn );
169172
173+ byte [] classbytes = bb .array ();
174+
175+ byte [] classBytesModified = transformers .transform (cn , classbytes );
176+
177+ if (classBytesModified != null ) {
178+ Class <?> clz = defineClass (cn , classBytesModified , 0 , classBytesModified .length , loadedModule .getCodeSource ());
179+ transformers .add (cn , clz );
180+ return clz ;
181+ } else {
182+ try {
183+ return defineClass (cn , bb , loadedModule .getCodeSource ());
184+ } finally {
185+ reader .release (bb );
186+ }
187+ }
170188 } catch (IOException ioe ) {
171189 // TBD on how I/O errors should be propagated
172190 return null ;
0 commit comments