mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-27 06:45:07 +02:00
Merge
This commit is contained in:
commit
afd6c107a5
262 changed files with 21429 additions and 900 deletions
|
@ -13,6 +13,8 @@ pack.code.attribute.CoverageTable = NH[PHHII]
|
|||
pack.code.attribute.CharacterRangeTable = NH[PHPOHIIH]
|
||||
pack.class.attribute.SourceID = RUH
|
||||
pack.class.attribute.CompilationID = RUH
|
||||
pack.class.attribute.NestHost = RCH
|
||||
pack.class.attribute.NestMembers = NH[RCH]
|
||||
|
||||
# Note: Zero-length ("marker") attributes do not need to be specified here.
|
||||
# They are automatically defined to have an empty layout.
|
||||
|
|
|
@ -82,9 +82,9 @@ import sun.reflect.annotation.*;
|
|||
import sun.reflect.misc.ReflectUtil;
|
||||
|
||||
/**
|
||||
* Instances of the class {@code Class} represent classes and
|
||||
* interfaces in a running Java application. An enum is a kind of
|
||||
* class and an annotation is a kind of interface. Every array also
|
||||
* Instances of the class {@code Class} represent classes and interfaces
|
||||
* in a running Java application. An enum type is a kind of class and an
|
||||
* annotation type is a kind of interface. Every array also
|
||||
* belongs to a class that is reflected as a {@code Class} object
|
||||
* that is shared by all arrays with the same element type and number
|
||||
* of dimensions. The primitive Java types ({@code boolean},
|
||||
|
@ -93,10 +93,34 @@ import sun.reflect.misc.ReflectUtil;
|
|||
* {@code double}), and the keyword {@code void} are also
|
||||
* represented as {@code Class} objects.
|
||||
*
|
||||
* <p> {@code Class} has no public constructor. Instead {@code Class}
|
||||
* objects are constructed automatically by the Java Virtual Machine as classes
|
||||
* are loaded and by calls to the {@code defineClass} method in the class
|
||||
* loader.
|
||||
* <p> {@code Class} has no public constructor. Instead a {@code Class}
|
||||
* object is constructed automatically by the Java Virtual Machine
|
||||
* when a class loader invokes one of the
|
||||
* {@link ClassLoader#defineClass(String,byte[], int,int) defineClass} methods
|
||||
* and passes the bytes of a {@code class} file.
|
||||
*
|
||||
* <p> The methods of class {@code Class} expose many characteristics of a
|
||||
* class or interface. Most characteristics are derived from the {@code class}
|
||||
* file that the class loader passed to the Java Virtual Machine. A few
|
||||
* characteristics are determined by the class loading environment at run time,
|
||||
* such as the module returned by {@link #getModule() getModule()}.
|
||||
*
|
||||
* <p> Some methods of class {@code Class} expose whether the declaration of
|
||||
* a class or interface in Java source code was <em>enclosed</em> within
|
||||
* another declaration. Other methods describe how a class or interface
|
||||
* is situated in a <em>nest</em>. A <a id="nest">nest</a> is a set of
|
||||
* classes and interfaces, in the same run-time package, that
|
||||
* allow mutual access to their {@code private} members.
|
||||
* The classes and interfaces are known as <em>nestmates</em>.
|
||||
* One nestmate acts as the
|
||||
* <em>nest host</em>, and enumerates the other nestmates which
|
||||
* belong to the nest; each of them in turn records it as the nest host.
|
||||
* The classes and interfaces which belong to a nest, including its host, are
|
||||
* determined when
|
||||
* {@code class} files are generated, for example, a Java compiler
|
||||
* will typically record a top-level class as the host of a nest where the
|
||||
* other members are the classes and interfaces whose declarations are
|
||||
* enclosed within the top-level class declaration.
|
||||
*
|
||||
* <p> The following example uses a {@code Class} object to print the
|
||||
* class name of an object:
|
||||
|
@ -3848,4 +3872,161 @@ public final class Class<T> implements java.io.Serializable,
|
|||
public AnnotatedType[] getAnnotatedInterfaces() {
|
||||
return TypeAnnotationParser.buildAnnotatedInterfaces(getRawTypeAnnotations(), getConstantPool(), this);
|
||||
}
|
||||
|
||||
private native Class<?> getNestHost0();
|
||||
|
||||
/**
|
||||
* Returns the nest host of the <a href=#nest>nest</a> to which the class
|
||||
* or interface represented by this {@code Class} object belongs.
|
||||
* Every class and interface is a member of exactly one nest.
|
||||
* A class or interface that is not recorded as belonging to a nest
|
||||
* belongs to the nest consisting only of itself, and is the nest
|
||||
* host.
|
||||
*
|
||||
* <p>Each of the {@code Class} objects representing array types,
|
||||
* primitive types, and {@code void} returns {@code this} to indicate
|
||||
* that the represented entity belongs to the nest consisting only of
|
||||
* itself, and is the nest host.
|
||||
*
|
||||
* <p>If there is a {@linkplain LinkageError linkage error} accessing
|
||||
* the nest host, or if this class or interface is not enumerated as
|
||||
* a member of the nest by the nest host, then it is considered to belong
|
||||
* to its own nest and {@code this} is returned as the host.
|
||||
*
|
||||
* @apiNote A {@code class} file of version 55.0 or greater may record the
|
||||
* host of the nest to which it belongs by using the {@code NestHost}
|
||||
* attribute (JVMS 4.7.28). Alternatively, a {@code class} file of
|
||||
* version 55.0 or greater may act as a nest host by enumerating the nest's
|
||||
* other members with the
|
||||
* {@code NestMembers} attribute (JVMS 4.7.29).
|
||||
* A {@code class} file of version 54.0 or lower does not use these
|
||||
* attributes.
|
||||
*
|
||||
* @return the nest host of this class or interface
|
||||
*
|
||||
* @throws SecurityException
|
||||
* If the returned class is not the current class, and
|
||||
* if a security manager, <i>s</i>, is present and the caller's
|
||||
* class loader is not the same as or an ancestor of the class
|
||||
* loader for the returned class and invocation of {@link
|
||||
* SecurityManager#checkPackageAccess s.checkPackageAccess()}
|
||||
* denies access to the package of the returned class
|
||||
* @since 11
|
||||
* @jvms 4.7.28 and 4.7.29 NestHost and NestMembers attributes
|
||||
* @jvms 5.4.4 Access Control
|
||||
*/
|
||||
@CallerSensitive
|
||||
public Class<?> getNestHost() {
|
||||
if (isPrimitive() || isArray()) {
|
||||
return this;
|
||||
}
|
||||
Class<?> host;
|
||||
try {
|
||||
host = getNestHost0();
|
||||
} catch (LinkageError e) {
|
||||
// if we couldn't load our nest-host then we
|
||||
// act as-if we have no nest-host attribute
|
||||
return this;
|
||||
}
|
||||
// if null then nest membership validation failed, so we
|
||||
// act as-if we have no nest-host attribute
|
||||
if (host == null || host == this) {
|
||||
return this;
|
||||
}
|
||||
// returning a different class requires a security check
|
||||
SecurityManager sm = System.getSecurityManager();
|
||||
if (sm != null) {
|
||||
checkPackageAccess(sm,
|
||||
ClassLoader.getClassLoader(Reflection.getCallerClass()), true);
|
||||
}
|
||||
return host;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if the given {@code Class} is a nestmate of the
|
||||
* class or interface represented by this {@code Class} object.
|
||||
* Two classes or interfaces are nestmates
|
||||
* if they have the same {@linkplain #getNestHost() nest host}.
|
||||
*
|
||||
* @param c the class to check
|
||||
* @return {@code true} if this class and {@code c} are members of
|
||||
* the same nest; and {@code false} otherwise.
|
||||
*
|
||||
* @since 11
|
||||
*/
|
||||
public boolean isNestmateOf(Class<?> c) {
|
||||
if (this == c) {
|
||||
return true;
|
||||
}
|
||||
if (isPrimitive() || isArray() ||
|
||||
c.isPrimitive() || c.isArray()) {
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
return getNestHost0() == c.getNestHost0();
|
||||
} catch (LinkageError e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private native Class<?>[] getNestMembers0();
|
||||
|
||||
/**
|
||||
* Returns an array containing {@code Class} objects representing all the
|
||||
* classes and interfaces that are members of the nest to which the class
|
||||
* or interface represented by this {@code Class} object belongs.
|
||||
* The {@linkplain #getNestHost() nest host} of that nest is the zeroth
|
||||
* element of the array. Subsequent elements represent any classes or
|
||||
* interfaces that are recorded by the nest host as being members of
|
||||
* the nest; the order of such elements is unspecified. Duplicates are
|
||||
* permitted.
|
||||
* If the nest host of that nest does not enumerate any members, then the
|
||||
* array has a single element containing {@code this}.
|
||||
*
|
||||
* <p>Each of the {@code Class} objects representing array types,
|
||||
* primitive types, and {@code void} returns an array containing only
|
||||
* {@code this}.
|
||||
*
|
||||
* <p>This method validates that, for each class or interface which is
|
||||
* recorded as a member of the nest by the nest host, that class or
|
||||
* interface records itself as a member of that same nest. Any exceptions
|
||||
* that occur during this validation are rethrown by this method.
|
||||
*
|
||||
* @return an array of all classes and interfaces in the same nest as
|
||||
* this class
|
||||
*
|
||||
* @throws LinkageError
|
||||
* If there is any problem loading or validating a nest member or
|
||||
* its nest host
|
||||
* @throws SecurityException
|
||||
* If any returned class is not the current class, and
|
||||
* if a security manager, <i>s</i>, is present and the caller's
|
||||
* class loader is not the same as or an ancestor of the class
|
||||
* loader for that returned class and invocation of {@link
|
||||
* SecurityManager#checkPackageAccess s.checkPackageAccess()}
|
||||
* denies access to the package of that returned class
|
||||
*
|
||||
* @since 11
|
||||
* @see #getNestHost()
|
||||
*/
|
||||
@CallerSensitive
|
||||
public Class<?>[] getNestMembers() {
|
||||
if (isPrimitive() || isArray()) {
|
||||
return new Class<?>[] { this };
|
||||
}
|
||||
Class<?>[] members = getNestMembers0();
|
||||
// Can't actually enable this due to bootstrapping issues
|
||||
// assert(members.length != 1 || members[0] == this); // expected invariant from VM
|
||||
|
||||
if (members.length > 1) {
|
||||
// If we return anything other than the current class we need
|
||||
// a security check
|
||||
SecurityManager sm = System.getSecurityManager();
|
||||
if (sm != null) {
|
||||
checkPackageAccess(sm,
|
||||
ClassLoader.getClassLoader(Reflection.getCallerClass()), true);
|
||||
}
|
||||
}
|
||||
return members;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -58,7 +58,8 @@ class DirectMethodHandle extends MethodHandle {
|
|||
if (!member.isResolved()) throw new InternalError();
|
||||
|
||||
if (member.getDeclaringClass().isInterface() &&
|
||||
member.isMethod() && !member.isAbstract()) {
|
||||
member.getReferenceKind() == REF_invokeInterface &&
|
||||
member.isMethod() && !member.isAbstract()) {
|
||||
// Check for corner case: invokeinterface of Object method
|
||||
MemberName m = new MemberName(Object.class, member.getName(), member.getMethodType(), member.getReferenceKind());
|
||||
m = MemberName.getFactory().resolveOrNull(m.getReferenceKind(), m, null);
|
||||
|
@ -80,22 +81,28 @@ class DirectMethodHandle extends MethodHandle {
|
|||
mtype = mtype.insertParameterTypes(0, refc);
|
||||
}
|
||||
if (!member.isField()) {
|
||||
// refKind reflects the original type of lookup via findSpecial or
|
||||
// findVirtual etc.
|
||||
switch (refKind) {
|
||||
case REF_invokeSpecial: {
|
||||
member = member.asSpecial();
|
||||
LambdaForm lform = preparedLambdaForm(member, callerClass);
|
||||
Class<?> checkClass = refc; // Class to use for receiver type check
|
||||
if (callerClass != null) {
|
||||
checkClass = callerClass; // potentially strengthen to caller class
|
||||
// if caller is an interface we need to adapt to get the
|
||||
// receiver check inserted
|
||||
if (callerClass == null) {
|
||||
throw new InternalError("callerClass must not be null for REF_invokeSpecial");
|
||||
}
|
||||
return new Special(mtype, lform, member, checkClass);
|
||||
LambdaForm lform = preparedLambdaForm(member, callerClass.isInterface());
|
||||
return new Special(mtype, lform, member, callerClass);
|
||||
}
|
||||
case REF_invokeInterface: {
|
||||
LambdaForm lform = preparedLambdaForm(member, callerClass);
|
||||
// for interfaces we always need the receiver typecheck,
|
||||
// so we always pass 'true' to ensure we adapt if needed
|
||||
// to include the REF_invokeSpecial case
|
||||
LambdaForm lform = preparedLambdaForm(member, true);
|
||||
return new Interface(mtype, lform, member, refc);
|
||||
}
|
||||
default: {
|
||||
LambdaForm lform = preparedLambdaForm(member, callerClass);
|
||||
LambdaForm lform = preparedLambdaForm(member);
|
||||
return new DirectMethodHandle(mtype, lform, member);
|
||||
}
|
||||
}
|
||||
|
@ -165,11 +172,16 @@ class DirectMethodHandle extends MethodHandle {
|
|||
* Cache and share this structure among all methods with
|
||||
* the same basicType and refKind.
|
||||
*/
|
||||
private static LambdaForm preparedLambdaForm(MemberName m, Class<?> callerClass) {
|
||||
private static LambdaForm preparedLambdaForm(MemberName m, boolean adaptToSpecialIfc) {
|
||||
assert(m.isInvocable()) : m; // call preparedFieldLambdaForm instead
|
||||
MethodType mtype = m.getInvocationType().basicType();
|
||||
assert(!m.isMethodHandleInvoke()) : m;
|
||||
int which;
|
||||
// MemberName.getReferenceKind represents the JVM optimized form of the call
|
||||
// as distinct from the "kind" passed to DMH.make which represents the original
|
||||
// bytecode-equivalent request. Specifically private/final methods that use a direct
|
||||
// call have getReferenceKind adapted to REF_invokeSpecial, even though the actual
|
||||
// invocation mode may be invokevirtual or invokeinterface.
|
||||
switch (m.getReferenceKind()) {
|
||||
case REF_invokeVirtual: which = LF_INVVIRTUAL; break;
|
||||
case REF_invokeStatic: which = LF_INVSTATIC; break;
|
||||
|
@ -183,7 +195,7 @@ class DirectMethodHandle extends MethodHandle {
|
|||
preparedLambdaForm(mtype, which);
|
||||
which = LF_INVSTATIC_INIT;
|
||||
}
|
||||
if (which == LF_INVSPECIAL && callerClass != null && callerClass.isInterface()) {
|
||||
if (which == LF_INVSPECIAL && adaptToSpecialIfc) {
|
||||
which = LF_INVSPECIAL_IFC;
|
||||
}
|
||||
LambdaForm lform = preparedLambdaForm(mtype, which);
|
||||
|
@ -195,7 +207,7 @@ class DirectMethodHandle extends MethodHandle {
|
|||
}
|
||||
|
||||
private static LambdaForm preparedLambdaForm(MemberName m) {
|
||||
return preparedLambdaForm(m, null);
|
||||
return preparedLambdaForm(m, false);
|
||||
}
|
||||
|
||||
private static LambdaForm preparedLambdaForm(MethodType mtype, int which) {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2008, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -250,6 +250,9 @@ import static java.lang.invoke.MethodHandleStatics.*;
|
|||
* can also be created. These do not perform virtual lookup based on
|
||||
* receiver type. Such a method handle simulates the effect of
|
||||
* an {@code invokespecial} instruction to the same method.
|
||||
* A non-virtual method handle can also be created to simulate the effect
|
||||
* of an {@code invokevirtual} or {@code invokeinterface} instruction on
|
||||
* a private method (as applicable).
|
||||
*
|
||||
* <h1>Usage examples</h1>
|
||||
* Here are some examples of usage:
|
||||
|
|
|
@ -469,15 +469,20 @@ public class MethodHandles {
|
|||
* methods as if they were normal methods, but the JVM bytecode verifier rejects them.
|
||||
* A lookup of such an internal method will produce a {@code NoSuchMethodException}.
|
||||
* <p>
|
||||
* In some cases, access between nested classes is obtained by the Java compiler by creating
|
||||
* an wrapper method to access a private method of another class
|
||||
* in the same top-level declaration.
|
||||
* If the relationship between nested types is expressed directly through the
|
||||
* {@code NestHost} and {@code NestMembers} attributes
|
||||
* (see the Java Virtual Machine Specification, sections 4.7.28 and 4.7.29),
|
||||
* then the associated {@code Lookup} object provides direct access to
|
||||
* the lookup class and all of its nestmates
|
||||
* (see {@link java.lang.Class#getNestHost Class.getNestHost}).
|
||||
* Otherwise, access between nested classes is obtained by the Java compiler creating
|
||||
* a wrapper method to access a private method of another class in the same nest.
|
||||
* For example, a nested class {@code C.D}
|
||||
* can access private members within other related classes such as
|
||||
* {@code C}, {@code C.D.E}, or {@code C.B},
|
||||
* but the Java compiler may need to generate wrapper methods in
|
||||
* those related classes. In such cases, a {@code Lookup} object on
|
||||
* {@code C.E} would be unable to those private members.
|
||||
* {@code C.E} would be unable to access those private members.
|
||||
* A workaround for this limitation is the {@link Lookup#in Lookup.in} method,
|
||||
* which can transform a lookup on {@code C.E} into one on any of those other
|
||||
* classes, without special elevation of privilege.
|
||||
|
@ -499,11 +504,12 @@ public class MethodHandles {
|
|||
* <em>Discussion of private access:</em>
|
||||
* We say that a lookup has <em>private access</em>
|
||||
* if its {@linkplain #lookupModes lookup modes}
|
||||
* include the possibility of accessing {@code private} members.
|
||||
* include the possibility of accessing {@code private} members
|
||||
* (which includes the private members of nestmates).
|
||||
* As documented in the relevant methods elsewhere,
|
||||
* only lookups with private access possess the following capabilities:
|
||||
* <ul style="font-size:smaller;">
|
||||
* <li>access private fields, methods, and constructors of the lookup class
|
||||
* <li>access private fields, methods, and constructors of the lookup class and its nestmates
|
||||
* <li>create method handles which invoke <a href="MethodHandles.Lookup.html#callsens">caller sensitive</a> methods,
|
||||
* such as {@code Class.forName}
|
||||
* <li>create method handles which {@link Lookup#findSpecial emulate invokespecial} instructions
|
||||
|
@ -728,9 +734,7 @@ public class MethodHandles {
|
|||
* <p>
|
||||
* A freshly-created lookup object
|
||||
* on the {@linkplain java.lang.invoke.MethodHandles#lookup() caller's class} has
|
||||
* all possible bits set, except {@code UNCONDITIONAL}. The lookup can be used to
|
||||
* access all members of the caller's class, all public types in the caller's module,
|
||||
* and all public types in packages exported by other modules to the caller's module.
|
||||
* all possible bits set, except {@code UNCONDITIONAL}.
|
||||
* A lookup object on a new lookup class
|
||||
* {@linkplain java.lang.invoke.MethodHandles.Lookup#in created from a previous lookup object}
|
||||
* may have some mode bits set to zero.
|
||||
|
@ -1106,8 +1110,9 @@ assertEquals("[x, y]", MH_asList.invoke("x", "y").toString());
|
|||
* The method and all its argument types must be accessible to the lookup object.
|
||||
* <p>
|
||||
* When called, the handle will treat the first argument as a receiver
|
||||
* and dispatch on the receiver's type to determine which method
|
||||
* and, for non-private methods, dispatch on the receiver's type to determine which method
|
||||
* implementation to enter.
|
||||
* For private methods the named method in {@code refc} will be invoked on the receiver.
|
||||
* (The dispatching action is identical with that performed by an
|
||||
* {@code invokevirtual} or {@code invokeinterface} instruction.)
|
||||
* <p>
|
||||
|
@ -1171,7 +1176,6 @@ assertEquals("", (String) MH_newString.invokeExact());
|
|||
* @throws NoSuchMethodException if the method does not exist
|
||||
* @throws IllegalAccessException if access checking fails,
|
||||
* or if the method is {@code static},
|
||||
* or if the method is {@code private} method of interface,
|
||||
* or if the method's variable arity modifier bit
|
||||
* is set and {@code asVarargsCollector} fails
|
||||
* @exception SecurityException if a security manager is present and it
|
||||
|
@ -2225,17 +2229,13 @@ return mh1;
|
|||
return "member is private to package";
|
||||
}
|
||||
|
||||
private static final boolean ALLOW_NESTMATE_ACCESS = false;
|
||||
|
||||
private void checkSpecialCaller(Class<?> specialCaller, Class<?> refc) throws IllegalAccessException {
|
||||
int allowedModes = this.allowedModes;
|
||||
if (allowedModes == TRUSTED) return;
|
||||
if (!hasPrivateAccess()
|
||||
|| (specialCaller != lookupClass()
|
||||
// ensure non-abstract methods in superinterfaces can be special-invoked
|
||||
&& !(refc != null && refc.isInterface() && refc.isAssignableFrom(specialCaller))
|
||||
&& !(ALLOW_NESTMATE_ACCESS &&
|
||||
VerifyAccess.isSamePackageMember(specialCaller, lookupClass()))))
|
||||
&& !(refc != null && refc.isInterface() && refc.isAssignableFrom(specialCaller))))
|
||||
throw new MemberName(specialCaller).
|
||||
makeAccessException("no private access for invokespecial", this);
|
||||
}
|
||||
|
@ -2246,9 +2246,7 @@ return mh1;
|
|||
if (!method.isProtected() || method.isStatic()
|
||||
|| allowedModes == TRUSTED
|
||||
|| method.getDeclaringClass() == lookupClass()
|
||||
|| VerifyAccess.isSamePackage(method.getDeclaringClass(), lookupClass())
|
||||
|| (ALLOW_NESTMATE_ACCESS &&
|
||||
VerifyAccess.isSamePackageMember(method.getDeclaringClass(), lookupClass())))
|
||||
|| VerifyAccess.isSamePackage(method.getDeclaringClass(), lookupClass()))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
@ -2288,6 +2286,7 @@ return mh1;
|
|||
private MethodHandle getDirectMethodCommon(byte refKind, Class<?> refc, MemberName method,
|
||||
boolean checkSecurity,
|
||||
boolean doRestrict, Class<?> boundCallerClass) throws IllegalAccessException {
|
||||
|
||||
checkMethod(refKind, refc, method);
|
||||
// Optionally check with the security manager; this isn't needed for unreflect* calls.
|
||||
if (checkSecurity)
|
||||
|
@ -2300,6 +2299,7 @@ return mh1;
|
|||
refc != lookupClass().getSuperclass() &&
|
||||
refc.isAssignableFrom(lookupClass())) {
|
||||
assert(!method.getName().equals("<init>")); // not this code path
|
||||
|
||||
// Per JVMS 6.5, desc. of invokespecial instruction:
|
||||
// If the method is in a superclass of the LC,
|
||||
// and if our original search was above LC.super,
|
||||
|
|
|
@ -47,7 +47,7 @@ import sun.security.util.SecurityConstants;
|
|||
* in a manner that would normally be prohibited.
|
||||
*
|
||||
* <p> Java language access control prevents use of private members outside
|
||||
* their class; package access members outside their package; protected members
|
||||
* their top-level class; package access members outside their package; protected members
|
||||
* outside their package or subclasses; and public members outside their
|
||||
* module unless they are declared in an {@link Module#isExported(String,Module)
|
||||
* exported} package and the user {@link Module#canRead reads} their module. By
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 1996, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1996, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -505,8 +505,8 @@ public final class Method extends Executable {
|
|||
*
|
||||
* <p>If the underlying method is an instance method, it is invoked
|
||||
* using dynamic method lookup as documented in The Java Language
|
||||
* Specification, Second Edition, section 15.12.4.4; in particular,
|
||||
* overriding based on the runtime type of the target object will occur.
|
||||
* Specification, section 15.12.4.4; in particular,
|
||||
* overriding based on the runtime type of the target object may occur.
|
||||
*
|
||||
* <p>If the underlying method is static, the class that declared
|
||||
* the method is initialized if it has not already been initialized.
|
||||
|
|
|
@ -58,6 +58,8 @@
|
|||
*/
|
||||
package jdk.internal.org.objectweb.asm;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* A non standard class, field, method or code attribute.
|
||||
*
|
||||
|
@ -281,4 +283,72 @@ public class Attribute {
|
|||
attr = attr.next;
|
||||
}
|
||||
}
|
||||
|
||||
//The stuff below is temporary - once proper support for nestmate attribute has been added, it can be safely removed.
|
||||
//see also changes in ClassReader.accept.
|
||||
|
||||
public static class NestMembers extends Attribute {
|
||||
public NestMembers() {
|
||||
super("NestMembers");
|
||||
}
|
||||
|
||||
byte[] bytes;
|
||||
String[] classes;
|
||||
|
||||
@Override
|
||||
protected Attribute read(ClassReader cr, int off, int len, char[] buf, int codeOff, Label[] labels) {
|
||||
int offset = off;
|
||||
NestMembers a = new NestMembers();
|
||||
int size = cr.readShort(off);
|
||||
a.classes = new String[size];
|
||||
off += 2;
|
||||
for (int i = 0; i < size ; i++) {
|
||||
a.classes[i] = cr.readClass(off, buf);
|
||||
off += 2;
|
||||
}
|
||||
a.bytes = Arrays.copyOfRange(cr.b, offset, offset + len);
|
||||
return a;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ByteVector write(ClassWriter cw, byte[] code, int len, int maxStack, int maxLocals) {
|
||||
ByteVector v = new ByteVector(bytes.length);
|
||||
v.putShort(classes.length);
|
||||
for (String s : classes) {
|
||||
v.putShort(cw.newClass(s));
|
||||
}
|
||||
return v;
|
||||
}
|
||||
}
|
||||
|
||||
public static class NestHost extends Attribute {
|
||||
|
||||
byte[] bytes;
|
||||
String clazz;
|
||||
|
||||
public NestHost() {
|
||||
super("NestHost");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Attribute read(ClassReader cr, int off, int len, char[] buf, int codeOff, Label[] labels) {
|
||||
int offset = off;
|
||||
NestHost a = new NestHost();
|
||||
a.clazz = cr.readClass(off, buf);
|
||||
a.bytes = Arrays.copyOfRange(cr.b, offset, offset + len);
|
||||
return a;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ByteVector write(ClassWriter cw, byte[] code, int len, int maxStack, int maxLocals) {
|
||||
ByteVector v = new ByteVector(bytes.length);
|
||||
v.putShort(cw.newClass(clazz));
|
||||
return v;
|
||||
}
|
||||
}
|
||||
|
||||
static final Attribute[] DEFAULT_ATTRIBUTE_PROTOS = new Attribute[] {
|
||||
new NestMembers(),
|
||||
new NestHost()
|
||||
};
|
||||
}
|
||||
|
|
|
@ -530,7 +530,7 @@ public class ClassReader {
|
|||
* , {@link #SKIP_FRAMES}, {@link #SKIP_CODE}.
|
||||
*/
|
||||
public void accept(final ClassVisitor classVisitor, final int flags) {
|
||||
accept(classVisitor, new Attribute[0], flags);
|
||||
accept(classVisitor, Attribute.DEFAULT_ATTRIBUTE_PROTOS, flags);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -629,14 +629,10 @@ class MethodAccessorGenerator extends AccessorGenerator {
|
|||
typeSizeInStackSlots(returnType));
|
||||
} else {
|
||||
if (isInterface()) {
|
||||
if (isPrivate()) {
|
||||
cb.opc_invokespecial(targetMethodRef, count, 0);
|
||||
} else {
|
||||
cb.opc_invokeinterface(targetMethodRef,
|
||||
count,
|
||||
count,
|
||||
typeSizeInStackSlots(returnType));
|
||||
}
|
||||
cb.opc_invokeinterface(targetMethodRef,
|
||||
count,
|
||||
count,
|
||||
typeSizeInStackSlots(returnType));
|
||||
} else {
|
||||
cb.opc_invokevirtual(targetMethodRef,
|
||||
count,
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2001, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -143,6 +143,15 @@ public class Reflection {
|
|||
return true;
|
||||
}
|
||||
|
||||
// Check for nestmate access if member is private
|
||||
if (Modifier.isPrivate(modifiers)) {
|
||||
// Note: targetClass may be outside the nest, but that is okay
|
||||
// as long as memberClass is in the nest.
|
||||
if (areNestMates(currentClass, memberClass)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
boolean successSoFar = false;
|
||||
|
||||
if (Modifier.isProtected(modifiers)) {
|
||||
|
@ -351,4 +360,12 @@ public class Reflection {
|
|||
|
||||
return new IllegalAccessException(msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if {@code currentClass} and {@code memberClass}
|
||||
* are nestmates - that is, if they have the same nesthost as
|
||||
* determined by the VM.
|
||||
*/
|
||||
public static native boolean areNestMates(Class<?> currentClass,
|
||||
Class<?> memberClass);
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2008, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -44,7 +44,6 @@ public class VerifyAccess {
|
|||
private static final int PACKAGE_ALLOWED = java.lang.invoke.MethodHandles.Lookup.PACKAGE;
|
||||
private static final int PROTECTED_OR_PACKAGE_ALLOWED = (PACKAGE_ALLOWED|PROTECTED);
|
||||
private static final int ALL_ACCESS_MODES = (PUBLIC|PRIVATE|PROTECTED|PACKAGE_ONLY);
|
||||
private static final boolean ALLOW_NESTMATE_ACCESS = false;
|
||||
|
||||
/**
|
||||
* Evaluate the JVM linkage rules for access to the given method
|
||||
|
@ -62,23 +61,29 @@ public class VerifyAccess {
|
|||
* the defining class should be passed for both arguments ({@code defc == refc}).
|
||||
* <h3>JVM Specification, 5.4.4 "Access Control"</h3>
|
||||
* A field or method R is accessible to a class or interface D if
|
||||
* and only if any of the following conditions is true:<ul>
|
||||
* <li>R is public.
|
||||
* and only if any of the following is true:
|
||||
* <ul>
|
||||
* <li>R is public.</li>
|
||||
* <li>R is protected and is declared in a class C, and D is either
|
||||
* a subclass of C or C itself. Furthermore, if R is not
|
||||
* static, then the symbolic reference to R must contain a
|
||||
* symbolic reference to a class T, such that T is either a
|
||||
* subclass of D, a superclass of D or D itself.
|
||||
* <li>R is either protected or has default access (that is,
|
||||
* neither public nor protected nor private), and is declared
|
||||
* by a class in the same runtime package as D.
|
||||
* <li>R is private and is declared in D.
|
||||
* a subclass of C or C itself. Furthermore, if R is not static,
|
||||
* then the symbolic reference to R must contain a symbolic
|
||||
* reference to a class T, such that T is either a subclass of D,
|
||||
* a superclass of D, or D itself.
|
||||
* <p>During verification, it was also required that, even if T is
|
||||
* a superclass of D, the target reference of a protected instance
|
||||
* field access or method invocation must be an instance of D or a
|
||||
* subclass of D (4.10.1.8).</p></li>
|
||||
* <li>R is either protected or has default access (that is, neither
|
||||
* public nor protected nor private), and is declared by a class
|
||||
* in the same run-time package as D.</li>
|
||||
* <li>R is private and is declared in D by a class or interface
|
||||
* belonging to the same nest as D.</li>
|
||||
* </ul>
|
||||
* This discussion of access control omits a related restriction
|
||||
* on the target of a protected field access or method invocation
|
||||
* (the target must be of class D or a subtype of D). That
|
||||
* requirement is checked as part of the verification process
|
||||
* (5.4.1); it is not part of link-time access control.
|
||||
* If a referenced field or method is not accessible, access checking
|
||||
* throws an IllegalAccessError. If an exception is thrown while
|
||||
* attempting to determine the nest host of a class or interface,
|
||||
* access checking fails for the same reason.
|
||||
*
|
||||
* @param refc the class used in the symbolic reference to the proposed member
|
||||
* @param defc the class in which the proposed member is actually defined
|
||||
* @param mods modifier flags for the proposed member
|
||||
|
@ -98,9 +103,10 @@ public class VerifyAccess {
|
|||
return false;
|
||||
}
|
||||
// Usually refc and defc are the same, but verify defc also in case they differ.
|
||||
if (defc == lookupClass &&
|
||||
if (defc == lookupClass &&
|
||||
(allowedModes & PRIVATE) != 0)
|
||||
return true; // easy check; all self-access is OK
|
||||
return true; // easy check; all self-access is OK with a private lookup
|
||||
|
||||
switch (mods & ALL_ACCESS_MODES) {
|
||||
case PUBLIC:
|
||||
return true; // already checked above
|
||||
|
@ -126,10 +132,13 @@ public class VerifyAccess {
|
|||
return ((allowedModes & PACKAGE_ALLOWED) != 0 &&
|
||||
isSamePackage(defc, lookupClass));
|
||||
case PRIVATE:
|
||||
// Loosened rules for privates follows access rules for inner classes.
|
||||
return (ALLOW_NESTMATE_ACCESS &&
|
||||
(allowedModes & PRIVATE) != 0 &&
|
||||
isSamePackageMember(defc, lookupClass));
|
||||
// Rules for privates follows access rules for nestmates.
|
||||
boolean canAccess = ((allowedModes & PRIVATE) != 0 &&
|
||||
Reflection.areNestMates(defc, lookupClass));
|
||||
// for private methods the selected method equals the
|
||||
// resolved method - so refc == defc
|
||||
assert (canAccess && refc == defc) || !canAccess;
|
||||
return canAccess;
|
||||
default:
|
||||
throw new IllegalArgumentException("bad modifiers: "+Modifier.toString(mods));
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue