2828import com .fox2code .foxloader .utils .Platform ;
2929import com .fox2code .foxloader .utils .async .AsyncItrLinkedList ;
3030import com .fox2code .foxloader .utils .io .IOUtils ;
31+ import org .jetbrains .annotations .NotNull ;
3132
3233import java .io .ByteArrayOutputStream ;
3334import java .io .File ;
3839import java .security .*;
3940import java .util .*;
4041import java .util .concurrent .ConcurrentHashMap ;
42+ import java .util .function .BooleanSupplier ;
43+ import java .util .function .Consumer ;
4144import java .util .function .Function ;
45+ import java .util .function .Supplier ;
4246
4347public final class FoxClassLoader extends URLClassLoader implements ClassLoaderMarker {
4448 private static final String MIXIN_INFO = "org.spongepowered.asm.mixin.transformer.MixinInfo" ;
@@ -51,11 +55,12 @@ public final class FoxClassLoader extends URLClassLoader implements ClassLoaderM
5155 ClassLoader .registerAsParallelCapable ();
5256 }
5357
54- private final HashMap <String , CodeSource > codeSourceCache = new HashMap <>();
55- private final HashMap <String , FileInfo > fileInfoCache = new HashMap <>();
58+ private final NullCheckedHashMap <String , CodeSource > codeSourceCache = new NullCheckedHashMap <>();
59+ private final NullCheckedHashMap <String , FileInfo > fileInfoCache = new NullCheckedHashMap <>();
60+ private final FileInfoListHolder fileInfoListHolder = new FileInfoListHolder ();
5661 private final AsyncItrLinkedList <String > exclusions = new AsyncItrLinkedList <>();
57- private final HashMap <String , byte []> injectedClasses = new HashMap <>();
58- private final HashMap <String , URL > injectedResources = new HashMap <>();
62+ private final NullCheckedHashMap <String , byte []> injectedClasses = new NullCheckedHashMap <>();
63+ private final NullCheckedHashMap <String , URL > injectedResources = new NullCheckedHashMap <>();
5964 private URLClassLoader gameExclusiveSource ;
6065 private boolean allowLoadingGame ;
6166 private WrappedExtensions wrappedExtensions ;
@@ -282,12 +287,16 @@ public void injectMissingFileInfo(FileInfo fileInfo) {
282287 }
283288 }
284289 if (inCls ) {
285- this .fileInfoCache .putIfAbsent (urlStr , fileInfo );
290+ if (this .fileInfoCache .putIfAbsent (urlStr , fileInfo ) == null ) {
291+ this .fileInfoListHolder .addFileInfo (fileInfo );
292+ }
286293 }
287294 }
288295
289296 void injectMissingFileInfoUnchecked (FileInfo fileInfo ) {
290- this .fileInfoCache .putIfAbsent (fileInfo .source .toString (), fileInfo );
297+ if (this .fileInfoCache .putIfAbsent (fileInfo .source .toString (), fileInfo ) == null ) {
298+ this .fileInfoListHolder .addFileInfo (fileInfo );
299+ }
291300 }
292301
293302 @ Override
@@ -421,6 +430,7 @@ public void addFileToClassLoader(FileInfo fileInfo) {
421430 return ;
422431 }
423432 this .fileInfoCache .put (urlStr , fileInfo );
433+ this .fileInfoListHolder .addFileInfo (fileInfo );
424434 if (isJavaArchiveSafe (fileInfo )) {
425435 URL url = fileInfo .source ;
426436 if (fileInfo .jarPath != null ) {
@@ -561,7 +571,7 @@ public static boolean isGamePath(String path) {
561571 }
562572
563573 public Collection <FileInfo > loadingClassPath () {
564- return Collections .unmodifiableCollection (this .fileInfoCache . values ( ));
574+ return Collections .unmodifiableCollection (new ArrayList <>( this .fileInfoListHolder ));
565575 }
566576
567577 private static boolean isJavaArchiveSafe (FileInfo fileInfo ) {
@@ -625,4 +635,58 @@ public static abstract class WrappedExtensions {
625635
626636 public abstract void info (String message );
627637 }
638+
639+ private static final class NullCheckedHashMap <K , V > extends HashMap <K , V > {
640+ @ Override
641+ public V put (@ NotNull K key ,@ NotNull V value ) {
642+ Objects .requireNonNull (key );
643+ Objects .requireNonNull (value );
644+ return super .put (key , value );
645+ }
646+
647+ @ Override
648+ public V putIfAbsent (@ NotNull K key ,@ NotNull V value ) {
649+ Objects .requireNonNull (key );
650+ Objects .requireNonNull (value );
651+ return super .putIfAbsent (key , value );
652+ }
653+ }
654+
655+ private static final class FileInfoListHolder extends AbstractCollection <FileInfo > {
656+ private final Consumer <FileInfo > addFnc ;
657+ private final Supplier <Iterator <FileInfo >> iteratorFnc ;
658+ private int size ;
659+
660+ private FileInfoListHolder () {
661+ final ArrayList <FileInfo > fileInfos = new ArrayList <>();
662+ this .addFnc = fileInfos ::add ;
663+ final Supplier <Iterator <FileInfo >> fileInfosUnmodifiable =
664+ Collections .unmodifiableCollection (fileInfos )::iterator ;
665+ this .iteratorFnc = () -> {
666+ final Iterator <FileInfo > fileInfoIterator = fileInfosUnmodifiable .get ();
667+ final BooleanSupplier hasNext = fileInfoIterator ::hasNext ;
668+ final Supplier <FileInfo > next = fileInfoIterator ::next ;
669+ return new Iterator <FileInfo >() {
670+ @ Override public boolean hasNext () { return hasNext .getAsBoolean (); }
671+ @ Override public FileInfo next () { return next .get (); }
672+ };
673+ };
674+ this .size = 0 ;
675+ }
676+
677+ private void addFileInfo (FileInfo fileInfo ) {
678+ this .size ++;
679+ this .addFnc .accept (fileInfo );
680+ }
681+
682+ @ Override
683+ public @ NotNull Iterator <FileInfo > iterator () {
684+ return this .iteratorFnc .get ();
685+ }
686+
687+ @ Override
688+ public int size () {
689+ return this .size ;
690+ }
691+ }
628692}
0 commit comments