virtual method lookup and accessibility

J

Jay Foad

The language spec section 15.12.4.4 "Locate Method to Invoke" (http://
java.sun.com/docs/books/jls/third_edition/html/
expressions.html#15.12.4.4) describes how run-time virtual method
lookup works, and then says:

"The above procedure will always find a non-abstract, accessible
method to invoke, provided that all classes and interfaces in the
program have been consistently compiled."

Is this true? Specifically, is the method that's invoked always
"accessible" from the class containing the method invocation
expression?

I think this is a counter-example:

package A;
public class C {
protected void f() {
System.out.println("Hello from C");
}
}

package B;
public class D extends A.C {
protected void f() {
System.out.println("Hello from D");
}
}

package A;
public class E {
public static void main(String args[]) {
C c = new B.D();
c.f();
}
}

If I compile and run this I get:

$ javac ?/*.java
$ java A.E
Hello from D

So A.E has invoked B.D.f(); but B.D.f() is not accessible from A.E,
because it is protected and in a different package.

Is this a bug in the language spec?

Thanks,
Jay.
 
L

Lew

Jay said:
The language spec section 15.12.4.4 "Locate Method to Invoke" (http://
java.sun.com/docs/books/jls/third_edition/html/
expressions.html#15.12.4.4) describes how run-time virtual method
lookup works, and then says:

"The above procedure will always find a non-abstract, accessible
method to invoke, provided that all classes and interfaces in the
program have been consistently compiled."

Is this true? Specifically, is the method that's invoked always
"accessible" from the class containing the method invocation
expression?

I think this is a counter-example:

package A;
public class C {
protected void f() {
System.out.println("Hello from C");
}
}

package B;
public class D extends A.C {
protected void f() {
System.out.println("Hello from D");
}
}

package A;
public class E {
public static void main(String args[]) {
C c = new B.D();
c.f();
}
}

If I compile and run this I get:

$ javac ?/*.java
$ java A.E
Hello from D

So A.E has invoked B.D.f(); but B.D.f() is not accessible from A.E,
because it is protected and in a different package.

Is this a bug in the language spec?

No. 'E' is in package 'A' as is 'C', therefore 'C#c' is accessible to 'E'. The fact that 'C' dispatches to 'D' is visible and accessible to 'C', not 'E'.
 
K

kedar mhaswade

The language spec section 15.12.4.4 "Locate Method to Invoke" (http://
java.sun.com/docs/books/jls/third_edition/html/
expressions.html#15.12.4.4) describes how run-time virtual method
lookup works, and then says:

"The above procedure will always find a non-abstract, accessible
method to invoke, provided that all classes and interfaces in the
program have been consistently compiled."

Is this true? Specifically, is the method that's invoked always
"accessible" from the class containing the method invocation
expression?

I think this is a counter-example:

package A;
public class C {
    protected void f() {
        System.out.println("Hello from C");
    }

}

package B;
public class D extends A.C {
    protected void f() {
        System.out.println("Hello from D");
    }

}

package A;
public class E {
    public static void main(String args[]) {
        C c = new B.D();
        c.f();
    }

}

If I compile and run this I get:

$ javac ?/*.java
$ java A.E
Hello from D

So A.E has invoked B.D.f(); but B.D.f() is not accessible from A.E,
because it is protected and in a different package.

Is this a bug in the language spec?

Thanks,
Jay.

Interesting!
This appears an anomaly, however the two bullet points at
http://java.sun.com/docs/books/jls/third_edition/html/expressions.html#250473
seem to cover the curious case where although B.D.f() (, which
"overrides" A.C.f()) is inaccessible to A.E when invoked on an
instance whose compile time type is B.D, the resolution at runtime
finds it when invoked on an instance of A.C.

This could be a spec bug, but compiler seems to behave as the spec
says.

(BTW, the package names should be all lower-case).
 
J

Jay Foad

Is this a bug in the language spec?

I mean: is it a bug that the spec claims that the method found will always be accessible? Should the word "accessible" be removed, like this:

"The above procedure will always find a non-abstract method to invoke, ..."

Jay.
 
R

Roedy Green

The language spec section 15.12.4.4 "Locate Method to Invoke" (http://
java.sun.com/docs/books/jls/third_edition/html/

Gosling tried to leave as scope as possible for innovation, so the
spec is pretty vague and abstract. To understand how a concrete
implementation might work, try reading some of Bjarne Stroustrup's
books. His Design and Evolution of C++ and the tech ref manual
explain how virtual methods can be implemented. Look for VTBL in the
index. I had an orgasmic Ah Ha moment when VTBLs suddenly clicked.
I had tried to invented them on my own unsuccessfully for my own
language.

A further technique I used earlier was studying assembler listings
from the Jet compiler. They no longer let you see the code. Customers
were worried it might make binaries easier to crack.
 
L

Lew

Jay said:
I mean: is it a bug that the spec claims that the method found will always be accessible? Should the word "accessible" be removed, like this:

"The above procedure will always find a non-abstract method to invoke, ..."

The answer is still no.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top