mirror of
https://github.com/VolmitSoftware/Iris.git
synced 2026-10-29 23:40:00 +00:00
Native provider loading
- Native provider classes load from the provider jars before the plugin class loader - Another plugin bundling VolmLib natives no longer supplies Iris native capabilities on Spigot - Tests cover provider jar classes taking precedence over the plugin loader
This commit is contained in:
1 parent
21ab5baf27
commit
c700138b66
2 files changed
+61
-2
No files matched your search
@@ -65,8 +65,7 @@ public final class NativeRuntimeLibraries {
|
||||
public URLClassLoader openProviderLoader(Path downloads) {
|
||||
try {
|
||||
List<URL> urls = providerUrls(downloads, NativeRuntimeLibraries.class.getClassLoader());
|
||||
URLClassLoader loader = new URLClassLoader("Iris native providers", urls.toArray(URL[]::new),
|
||||
NativeAdapters.class.getClassLoader());
|
||||
URLClassLoader loader = providerLoader(urls.toArray(URL[]::new), NativeAdapters.class.getClassLoader());
|
||||
NativeAdapters.registerProviderLoader(loader);
|
||||
return loader;
|
||||
} catch (IOException exception) {
|
||||
@@ -74,6 +73,10 @@ public final class NativeRuntimeLibraries {
|
||||
}
|
||||
}
|
||||
|
||||
static URLClassLoader providerLoader(URL[] urls, ClassLoader parent) {
|
||||
return new ProviderClassLoader(urls, parent);
|
||||
}
|
||||
|
||||
List<URL> providerUrls(Path downloads, ClassLoader resources) throws IOException {
|
||||
List<URL> urls = new ArrayList<>(providers.size());
|
||||
for (Provider provider : providers) {
|
||||
@@ -123,4 +126,28 @@ public final class NativeRuntimeLibraries {
|
||||
|
||||
private record Provider(String module, String version, String sha256) {
|
||||
}
|
||||
|
||||
private static final class ProviderClassLoader extends URLClassLoader {
|
||||
private ProviderClassLoader(URL[] urls, ClassLoader parent) {
|
||||
super("Iris native providers", urls, parent);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
|
||||
synchronized (getClassLoadingLock(name)) {
|
||||
Class<?> loaded = findLoadedClass(name);
|
||||
if (loaded == null) {
|
||||
try {
|
||||
loaded = findClass(name);
|
||||
} catch (ClassNotFoundException absent) {
|
||||
return super.loadClass(name, resolve);
|
||||
}
|
||||
}
|
||||
if (resolve) {
|
||||
resolveClass(loaded);
|
||||
}
|
||||
return loaded;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,8 @@ package art.arcane.iris.platform.bootstrap;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.TemporaryFolder;
|
||||
import org.objectweb.asm.ClassWriter;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
@@ -25,6 +27,7 @@ import java.util.stream.Stream;
|
||||
import static org.junit.Assert.assertArrayEquals;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertSame;
|
||||
import static org.junit.Assert.assertThrows;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
@@ -41,6 +44,20 @@ public class NativeRuntimeLibrariesTest {
|
||||
assertThrows(IllegalStateException.class, () -> NativeRuntimeLibraries.from(fixture.manifest(), "26.2.0"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void providerClassesLoadFromTheProviderJarBeforeThePluginLoader() throws Exception {
|
||||
String implementation = "art/arcane/volmlib/nativelib/v26_2_R1/Probe";
|
||||
String api = "art/arcane/volmlib/nativelib/Api";
|
||||
Path plugin = classJar("plugin.jar", implementation, api);
|
||||
Path provider = classJar("provider.jar", implementation);
|
||||
try (URLClassLoader parent = new URLClassLoader(new URL[]{plugin.toUri().toURL()}, null);
|
||||
URLClassLoader loader = NativeRuntimeLibraries.providerLoader(new URL[]{provider.toUri().toURL()}, parent)) {
|
||||
assertSame(loader, loader.loadClass(implementation.replace('/', '.')).getClassLoader());
|
||||
assertSame(parent, loader.loadClass(api.replace('/', '.')).getClassLoader());
|
||||
assertSame(String.class, loader.loadClass("java.lang.String"));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void rejectsMinecraftVersionsWithoutProvider() throws Exception {
|
||||
EmbeddedFixture fixture = embeddedFixture();
|
||||
@@ -156,6 +173,21 @@ public class NativeRuntimeLibrariesTest {
|
||||
return new EmbeddedFixture(properties, resources);
|
||||
}
|
||||
|
||||
private Path classJar(String name, String... classes) throws IOException {
|
||||
Path jar = temporary.newFolder().toPath().resolve(name);
|
||||
try (JarOutputStream output = new JarOutputStream(Files.newOutputStream(jar))) {
|
||||
for (String type : classes) {
|
||||
ClassWriter writer = new ClassWriter(0);
|
||||
writer.visit(Opcodes.V17, Opcodes.ACC_PUBLIC, type, null, "java/lang/Object", null);
|
||||
writer.visitEnd();
|
||||
output.putNextEntry(new JarEntry(type + ".class"));
|
||||
output.write(writer.toByteArray());
|
||||
output.closeEntry();
|
||||
}
|
||||
}
|
||||
return jar;
|
||||
}
|
||||
|
||||
private static void assertNoFailedExtract(Path downloads) throws IOException {
|
||||
try (Stream<Path> files = Files.walk(downloads)) {
|
||||
assertFalse(files.anyMatch(path -> Files.isRegularFile(path)
|
||||
|
||||
Reference in new issue
Block a user