Skip to content

Commit

Permalink
Align definePackage behavior with JRE modular classloaders
Browse files Browse the repository at this point in the history
  • Loading branch information
shartte committed Mar 28, 2024
1 parent f4a3e66 commit 464b664
Show file tree
Hide file tree
Showing 2 changed files with 1 addition and 82 deletions.
5 changes: 1 addition & 4 deletions src/main/java/cpw/mods/cl/ModuleClassLoader.java
Original file line number Diff line number Diff line change
Expand Up @@ -191,11 +191,8 @@ private Class<?> readerToClass(final ModuleReader reader, final ModuleReference
if (bytes.length == 0) return null;
var cname = name.replace('.','/')+".class";
var modroot = this.resolvedRoots.get(ref.descriptor().name());
ProtectionDomainHelper.tryDefinePackage(this, name, modroot.jar().getManifest(), t->modroot.jar().getManifest().getAttributes(t), this::definePackage); // Packages are dirctories, and can't be signed, so use raw attributes instead of signed.
var cs = ProtectionDomainHelper.createCodeSource(toURL(ref.location()), modroot.jar().verifyAndGetSigners(cname, bytes));
var cls = defineClass(name, bytes, 0, bytes.length, ProtectionDomainHelper.createProtectionDomain(cs, this));
ProtectionDomainHelper.trySetPackageModule(cls.getPackage(), cls.getModule());
return cls;
return defineClass(name, bytes, 0, bytes.length, ProtectionDomainHelper.createProtectionDomain(cs, this));
}

protected byte[] maybeTransformClassBytes(final byte[] bytes, final String name, final String context) {
Expand Down
78 changes: 0 additions & 78 deletions src/main/java/cpw/mods/cl/ProtectionDomainHelper.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,82 +29,4 @@ public static ProtectionDomain createProtectionDomain(CodeSource codeSource, Cla
}
}

private static final VarHandle PKG_MODULE_HANDLE;
static {
try {
// Obtain VarHandle for NamedPackage#module via trusted lookup
var trustedLookupField = MethodHandles.Lookup.class.getDeclaredField("IMPL_LOOKUP");
trustedLookupField.setAccessible(true);
MethodHandles.Lookup trustedLookup = (MethodHandles.Lookup) trustedLookupField.get(null);

Class<?> namedPackage = Class.forName("java.lang.NamedPackage");
PKG_MODULE_HANDLE = trustedLookup.findVarHandle(namedPackage, "module", Module.class);
} catch (Throwable t) {
throw new RuntimeException("Error finding package module handle", t);
}
}

static void trySetPackageModule(Package pkg, Module module) {
// Ensure named packages are bound to their module of origin
// Necessary for loading package-info classes
Module value = (Module) PKG_MODULE_HANDLE.get(pkg);
if (value == null || !value.isNamed()) {
try {
PKG_MODULE_HANDLE.set(pkg, module);
} catch (Throwable t) {
throw new RuntimeException("Error setting package module", t);
}
}
}

static Package tryDefinePackage(final ClassLoader classLoader, String name, Manifest man, Function<String, Attributes> trustedEntries, Function<String[], Package> definePackage) throws IllegalArgumentException
{
final var pname = name.substring(0, name.lastIndexOf('.'));
if (classLoader.getDefinedPackage(pname) == null) {
synchronized (classLoader) {
if (classLoader.getDefinedPackage(pname) != null) return classLoader.getDefinedPackage(pname);

String path = pname.replace('.', '/').concat("/");
String specTitle = null, specVersion = null, specVendor = null;
String implTitle = null, implVersion = null, implVendor = null;

if (man != null) {
Attributes attr = trustedEntries.apply(path);
if (attr != null) {
specTitle = attr.getValue(Attributes.Name.SPECIFICATION_TITLE);
specVersion = attr.getValue(Attributes.Name.SPECIFICATION_VERSION);
specVendor = attr.getValue(Attributes.Name.SPECIFICATION_VENDOR);
implTitle = attr.getValue(Attributes.Name.IMPLEMENTATION_TITLE);
implVersion = attr.getValue(Attributes.Name.IMPLEMENTATION_VERSION);
implVendor = attr.getValue(Attributes.Name.IMPLEMENTATION_VENDOR);
}
attr = man.getMainAttributes();
if (attr != null) {
if (specTitle == null) {
specTitle = attr.getValue(Attributes.Name.SPECIFICATION_TITLE);
}
if (specVersion == null) {
specVersion = attr.getValue(Attributes.Name.SPECIFICATION_VERSION);
}
if (specVendor == null) {
specVendor = attr.getValue(Attributes.Name.SPECIFICATION_VENDOR);
}
if (implTitle == null) {
implTitle = attr.getValue(Attributes.Name.IMPLEMENTATION_TITLE);
}
if (implVersion == null) {
implVersion = attr.getValue(Attributes.Name.IMPLEMENTATION_VERSION);
}
if (implVendor == null) {
implVendor = attr.getValue(Attributes.Name.IMPLEMENTATION_VENDOR);
}
}
}
return definePackage.apply(new String[]{pname, specTitle, specVersion, specVendor, implTitle, implVersion, implVendor});
}
} else {
return classLoader.getDefinedPackage(pname);
}
}

}

0 comments on commit 464b664

Please sign in to comment.