8332547: Unloaded signature classes in DirectMethodHandles

Reviewed-by: jvernee, liach
This commit is contained in:
Vladimir Ivanov 2024-06-04 04:02:49 +00:00
parent c7d2a5c1c4
commit 29e10e4582
4 changed files with 83 additions and 15 deletions

View file

@ -632,7 +632,7 @@ class InvokerBytecodeGenerator {
else if (c == Object[].class) return OBJARY;
else if (c == Class.class) return CLS;
else if (c == MethodHandle.class) return MH;
assert(VerifyAccess.isTypeVisible(c, Object.class)) : c.getName();
assert(VerifyAccess.ensureTypeVisible(c, Object.class)) : c.getName();
if (c == lastClass) {
return lastInternalName;

View file

@ -800,7 +800,7 @@ final class MemberName implements Member, Cloneable {
assert(isResolved() == isResolved);
}
void checkForTypeAlias(Class<?> refc) {
void ensureTypeVisible(Class<?> refc) {
if (isInvocable()) {
MethodType type;
if (this.type instanceof MethodType mt)
@ -808,7 +808,7 @@ final class MemberName implements Member, Cloneable {
else
this.type = type = getMethodType();
if (type.erase() == type) return;
if (VerifyAccess.isTypeVisible(type, refc)) return;
if (VerifyAccess.ensureTypeVisible(type, refc)) return;
throw new LinkageError("bad method type alias: "+type+" not visible from "+refc);
} else {
Class<?> type;
@ -816,7 +816,7 @@ final class MemberName implements Member, Cloneable {
type = cl;
else
this.type = type = getFieldType();
if (VerifyAccess.isTypeVisible(type, refc)) return;
if (VerifyAccess.ensureTypeVisible(type, refc)) return;
throw new LinkageError("bad field type alias: "+type+" not visible from "+refc);
}
}
@ -958,7 +958,7 @@ final class MemberName implements Member, Cloneable {
if (m == null && speculativeResolve) {
return null;
}
m.checkForTypeAlias(m.getDeclaringClass());
m.ensureTypeVisible(m.getDeclaringClass());
m.resolution = null;
} catch (ClassNotFoundException | LinkageError ex) {
// JVM reports that the "bytecode behavior" would get an error

View file

@ -268,7 +268,7 @@ public class VerifyAccess {
* @param type the supposed type of a member or symbolic reference of refc
* @param refc the class attempting to make the reference
*/
public static boolean isTypeVisible(Class<?> type, Class<?> refc) {
public static boolean ensureTypeVisible(Class<?> type, Class<?> refc) {
if (type == refc) {
return true; // easy check
}
@ -284,12 +284,14 @@ public class VerifyAccess {
if (refcLoader == null && typeLoader != null) {
return false;
}
if (typeLoader == null && type.getName().startsWith("java.")) {
// Note: The API for actually loading classes, ClassLoader.defineClass,
// guarantees that classes with names beginning "java." cannot be aliased,
// because class loaders cannot load them directly.
return true;
}
// The API for actually loading classes, ClassLoader.defineClass,
// guarantees that classes with names beginning "java." cannot be aliased,
// because class loaders cannot load them directly. However, it is beneficial
// for JIT-compilers to ensure all signature classes are loaded.
// JVM doesn't install any loader contraints when performing MemberName resolution,
// so eagerly resolving signature classes is a way to match what JVM achieves
// with loader constraints during method resolution for invoke bytecodes.
// Do it the hard way: Look up the type name from the refc loader.
//
@ -338,12 +340,12 @@ public class VerifyAccess {
* @param type the supposed type of a member or symbolic reference of refc
* @param refc the class attempting to make the reference
*/
public static boolean isTypeVisible(java.lang.invoke.MethodType type, Class<?> refc) {
if (!isTypeVisible(type.returnType(), refc)) {
public static boolean ensureTypeVisible(java.lang.invoke.MethodType type, Class<?> refc) {
if (!ensureTypeVisible(type.returnType(), refc)) {
return false;
}
for (int n = 0, max = type.parameterCount(); n < max; n++) {
if (!isTypeVisible(type.parameterType(n), refc)) {
if (!ensureTypeVisible(type.parameterType(n), refc)) {
return false;
}
}