Skip to content

Commit

Permalink
Fix bytecode transformation issue in DescriptionClassLoader.
Browse files Browse the repository at this point in the history
  • Loading branch information
Jan Boerman committed Dec 26, 2024
1 parent 88d1e94 commit aa1849f
Show file tree
Hide file tree
Showing 5 changed files with 22 additions and 23 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ private Object getCommodore(Server craftServer) throws Throwable {
}

// MC 1.20.5+ method signature of Commodore#convert:
public <ScalaPluginClassLoader extends ClassLoader & IScalaPluginClassLoader> byte[] transformNative(Server craftServer, byte[] classBytes, ScalaPluginClassLoader pluginClassLoader) throws Throwable {
public byte[] transformNative(Server craftServer, byte[] classBytes, ClassLoader pluginClassLoader, String pluginName, String apiVersionString) throws Throwable {
if (commodoreConvert == null && !attemptedToFindCommodoreConvert) {
attemptedToFindCommodoreConvert = true;
try {
Expand Down Expand Up @@ -133,12 +133,11 @@ public <ScalaPluginClassLoader extends ClassLoader & IScalaPluginClassLoader> by
}

if (commodoreConvert != null) {
String pluginName = getPluginName(pluginClassLoader);
try {
Class<?> apiVersionClass = getApiVersionClass();
MethodHandles.Lookup lookup = MethodHandles.lookup().in(apiVersionClass);
MethodHandle getOrCreateVersion = lookup.findStatic(apiVersionClass, "getOrCreateVersion", MethodType.methodType(apiVersionClass, String.class));
Object apiVersion = getOrCreateVersion.invoke(pluginClassLoader.getApiVersion().getVersionString());
Object apiVersion = getOrCreateVersion.invoke(apiVersionString);

Set activeCompatibilities = Collections.emptySet();
try {
Expand All @@ -156,6 +155,8 @@ public <ScalaPluginClassLoader extends ClassLoader & IScalaPluginClassLoader> by
}

// MC 1.13-1.20.4 method signature of Commodore#convert:
/** @deprecated do not call directly. Use {@linkplain #transform(String, byte[], ClassLoader)} instead. */
@Deprecated
public byte[] transformNative(Server craftServer, byte[] classBytes, boolean modern) throws Throwable {
if (!attemptedToFindCommodoreConvert) {
attemptedToFindCommodoreConvert = true;
Expand All @@ -181,20 +182,20 @@ public byte[] transformNative(Server craftServer, byte[] classBytes, boolean mod

@Override
public <ScalaPluginClassLoader extends ClassLoader & IScalaPluginClassLoader> byte[] transform(String jarEntryPath, byte[] classBytes, ScalaPluginClassLoader pluginClassLoader) throws Throwable {
ApiVersion apiVersion = pluginClassLoader.getApiVersion();
if (getApiVersionClass() != null) {
return transformNative(pluginClassLoader.getServer(), classBytes, pluginClassLoader);
return transformNative(pluginClassLoader.getServer(), classBytes, pluginClassLoader, getPluginName(pluginClassLoader), apiVersion.getVersionString());
} else {
return transformNative(pluginClassLoader.getServer(), classBytes, pluginClassLoader.getApiVersion() != ApiVersion.LEGACY);
return transformNative(pluginClassLoader.getServer(), classBytes, apiVersion != ApiVersion.LEGACY);
}
}

private static String getPluginName(IScalaPluginClassLoader classLoader) {
IScalaPlugin plugin = classLoader.getPlugin();
if (plugin == null) {
return FAKE_PLUGIN_NAME;
} else {
return plugin.getName();
public static String getPluginName(ClassLoader classLoader) {
if (classLoader instanceof IScalaPluginClassLoader) {
IScalaPlugin plugin = ((IScalaPluginClassLoader) classLoader).getPlugin();
if (plugin != null) return plugin.getName();
}
return FAKE_PLUGIN_NAME;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,8 @@ public enum ScalaVersion {
v3_6_1("3.6.1", false),
v3_6_2("3.6.2");

// When adding new entries here, don't forget to update ScalaHashes.

private static Map<String, ScalaVersion> byVersion = new HashMap<>();
private static final ScalaVersion latest_2_13;
static {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -597,7 +597,7 @@ private Optional<? extends DescriptionPlugin> buildDescriptionPlugin(File file,
try {
ScalaLibraryClassLoader scalaLibraryClassLoader = getOrCreateScalaLibrary(scalaDependency);
ClassLoader libraryLoader = createLibraryClassLoader(scalaLibraryClassLoader, scanResult.pluginYaml);
classLoader = new DescriptionClassLoader(file, libraryLoader, apiVersion != ApiVersion.LEGACY, mainClassName, scalaLibraryClassLoader.getScalaVersion());
classLoader = new DescriptionClassLoader(file, libraryLoader, apiVersion, mainClassName, scalaLibraryClassLoader.getScalaVersion());
} catch (ScalaPluginLoaderException e) {
getLogger().log(Level.SEVERE, "Could not download all libraries from plugin's description.", e);
return Optional.empty();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,6 @@
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
Expand Down Expand Up @@ -219,8 +216,7 @@ public Class<?> findClass(String name) throws ClassNotFoundException {
this.definePackage(pkgName, null, null, null, null, null, null, null);
}
} catch (IllegalArgumentException ex) {
// parallel-capable class loaders: re-verify in case of a
// race condition
// parallel-capable class loaders: re-verify in case of a race condition
if (this.getDefinedPackage(pkgName) == null) {
// Should never happen
throw new IllegalStateException("Cannot find package " + pkgName);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import xyz.janboerman.scalaloader.compat.Platform;
import xyz.janboerman.scalaloader.paper.plugin.ScalaPluginMeta;
import xyz.janboerman.scalaloader.paper.transform.MainClassBootstrapTransformer;
import xyz.janboerman.scalaloader.plugin.description.ApiVersion;

import java.io.File;
import java.io.IOException;
Expand All @@ -45,14 +46,14 @@ public class DescriptionClassLoader extends URLClassLoader implements Configured

private DescriptionPlugin plugin;
private PluginClassLoaderGroup classLoaderGroup;
private boolean modern;
private ApiVersion apiVersion;
private String mainClass;
private String scalaVersion;

public DescriptionClassLoader(File jarFile, ClassLoader parent, boolean modern, String mainClass, String scalaVersion) throws IOException {
public DescriptionClassLoader(File jarFile, ClassLoader parent, ApiVersion apiVersion, String mainClass, String scalaVersion) throws IOException {
super(new URL[] {jarFile.toURI().toURL()}, parent);
this.jarFile = Compat.jarFile(jarFile);
this.modern = modern;
this.apiVersion = apiVersion;
this.mainClass = mainClass;
this.scalaVersion = scalaVersion;
}
Expand All @@ -70,9 +71,8 @@ public Class<?> findClass(final String className) throws ClassNotFoundException
//transform the bytecode
//1. Bukkit's own migrations
try {
// TODO I don't think this will work still for newer versions of CraftBukkit.
// TODO check this, and fix this if it's broken.
byteCode = Platform.CRAFTBUKKIT.transformNative(Bukkit.getServer(), byteCode, modern); //we can assume Platform.CRAFTBUKKIT because we are running on Paper (which is a fork of CraftBukkit).
String pluginName = plugin != null ? plugin.getName() : "Owning plugin of class " + className;
byteCode = Platform.CRAFTBUKKIT.transformNative(Bukkit.getServer(), byteCode, this, pluginName, apiVersion.getVersionString()); //we can assume Platform.CRAFTBUKKIT because we are running on Paper (which is a fork of CraftBukkit).
} catch (Throwable e) {
Bukkit.getLogger().log(Level.SEVERE, "Server could not transform bytecode for class: " + className + ". This is a bug in " + Bukkit.getUnsafe().getClass().getName() + "#processClass", e);
}
Expand Down

0 comments on commit aa1849f

Please sign in to comment.