Hi Dan,
On 22/04/2017 2:54 AM, Dan Smith wrote:
On Apr 20, 2017, at 5:36 PM, David Holmes <david.hol...@oracle.com
<mailto:david.hol...@oracle.com>> wrote:
The rule is:
1) if the referenced method name is not <init> (cheap), and
2) if the referenced class name is the name of a superclass or direct
superinterface (cheap—superclass chain is already loaded), and
3) if the loaded referenced class actually is a superclass or direct
superinterface (almost always true and cheap, unless there's a name
clash), and
4) if the resolved method is not private (pretty cheap, because
referenced class is already loaded)
*then* check that the stack type is assignable to the current class type.
This is, essentially, the same logic being employed by the old
protected check: if the reference is to a superclass, find the
field/method and decide if it's protected; if the reference is to
some other class, don't worry about it.
So here's the problem, in the spec 5.4 states:
"Linking a class or interface involves verifying and preparing that
class or interface, its direct superclass, its direct superinterfaces,
and its element type (if it is an array type), if necessary.
Resolution of symbolic references in the class or interface is an
optional part of linking."
So resolution is _optional_ at link time! But your updated spec
requires resolution to happen before we can complete verification!
When we do the verification of invokespecial in the VM it is before
resolution and we do not know if the target method is private or not.
In the narrow case of an invokespecial in which (1), (2), and (3) are
true, yes, step (4) requires the verifier to find the declaration that
is being referenced and decide if it is 'private'.
This is the same as what the old 4.10.1.8 check has always required for
every invokevirtual, getfield, and putfield: in narrow circumstances,
track down the declared method and decide if it is <protected in another
package> or not.
I've tried to be careful not to claim this process is actually
resolution. It could be, but it could also be a simulation of resolution
that just tells you what method would be found if resolution occurred.
Specific text (tweaked slightly since published version): "Given a
symbolic reference to a field or method in class _ReferencedClass_ named
_MemberName_ with descriptor _MemberDescriptor_, identifies the field or
method _Member_ declared in class _DeclaringClass_ that would be
produced by resolution, as specified in [5.4.3]."
I am curious about the actual implemented details of this in the
protected check. I'm happy to make adjustments to the spec to align with
how we actually do this.
It looks like we do the "pseudo-resolution" of the method
(InstanceKlass::uncached_lookup_method()) or field
(InstanceKlass::find_field()).
I'm now curious about whether we essentially do this twice! That would
be very inefficient. :(
That aside, it seems it is okay for the spec to require this kind of
"look-ahead".
Thanks,
David
—Dan