package com.onthegomap.planetiler.util; import java.io.IOException; import java.io.UncheckedIOException; import java.util.Objects; import java.util.function.Predicate; /** * A class loader that loads certain classes even if they are already loaded by a parent classloader. * * This makes it possible to get multiple copies of the same class, so for example you could invoke a method * synchronized on a static variable from different classes without contention. */ public class DuplicateClassLoader extends ClassLoader { private final Predicate shouldDuplicate; private DuplicateClassLoader(Predicate shouldDuplicate) { this.shouldDuplicate = shouldDuplicate; } /** * Returns a {@link ClassLoader} that loads every class with a name starting with {@code prefix} even if the parent * has already loaded it. */ public static DuplicateClassLoader duplicateClassesWithPrefix(String prefix) { return new DuplicateClassLoader(name -> name.startsWith(prefix)); } @Override public Class loadClass(String name) throws ClassNotFoundException { if (shouldDuplicate.test(name)) { Class c = findLoadedClass(name); if (c == null) { byte[] b = loadClassFromFile(name); return defineClass(name, b, 0, b.length); } } return super.loadClass(name); } private byte[] loadClassFromFile(String fileName) { String classFileName = fileName.replace('.', '/') + ".class"; try (var inputStream = getClass().getClassLoader().getResourceAsStream(classFileName)) { return Objects.requireNonNull(inputStream, "Could not load " + fileName + " (" + classFileName + ")") .readAllBytes(); } catch (IOException e) { throw new UncheckedIOException(e); } } }