Skip to content

Commit 24a9c39

Browse files
committed
Improve classloader
1 parent a29ad71 commit 24a9c39

File tree

1 file changed

+71
-7
lines changed

1 file changed

+71
-7
lines changed

loader/src/main/java/com/fox2code/foxloader/launcher/FoxClassLoader.java

Lines changed: 71 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
import com.fox2code.foxloader.utils.Platform;
2929
import com.fox2code.foxloader.utils.async.AsyncItrLinkedList;
3030
import com.fox2code.foxloader.utils.io.IOUtils;
31+
import org.jetbrains.annotations.NotNull;
3132

3233
import java.io.ByteArrayOutputStream;
3334
import java.io.File;
@@ -38,7 +39,10 @@
3839
import java.security.*;
3940
import java.util.*;
4041
import java.util.concurrent.ConcurrentHashMap;
42+
import java.util.function.BooleanSupplier;
43+
import java.util.function.Consumer;
4144
import java.util.function.Function;
45+
import java.util.function.Supplier;
4246

4347
public 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

Comments
 (0)