invokevirtual on package private override in different classloader
Jeffrey Sinclair
jeff at cooljeff.co.uk
Tue Apr 14 14:33:15 PDT 2009
Karen,
Thanks for getting back to me.
I was using 1.6.0_10 and have now tried 1.6.0_13 and get the same
result. Specifically I've tried the following versions:
java version "1.6.0_10"
Java(TM) SE Runtime Environment (build 1.6.0_10-b33)
Java HotSpot(TM) 64-Bit Server VM (build 11.0-b15, mixed mode)
java version "1.6.0_13"
Java(TM) SE Runtime Environment (build 1.6.0_13-b03)
Java HotSpot(TM) 64-Bit Server VM (build 11.3-b02, mixed mode)
I've attached my source as Eclipse projects. The URL in the main method
points to the class files generated by the project with the
CustomSquare. I've also added some debug info relating to which class
loader is being used to load the Square, Printer and Custom Square
respectively:
Printer loaded by classloader: sun.misc.Launcher$AppClassLoader at 553f5d07
Square loaded by classloader: java.net.URLClassLoader at 3ae48e1b
CustomSquare loaded by classloader: java.net.URLClassLoader at 3ae48e1b
Red
I still get Red. The key point is that the CustomSquare is not visible
at all to the Printer code. If I stick the CustomSquare in the same
project as Printer it will then be loaded by the AppClassLoader and I
get blue. However when it is in a completely separate project and loaded
via the URLClassLoader (and Printer loaded via the AppClassLoader) I
always get Red. If I then change getColour() to be public in both Square
and CustomSquare I get blue.
This is completely baffling me. I may be doing something really silly
but I can't see it :)
Let me know if you can't replicate the issue with the attached Eclipse
project and I'll try to package it up using plain old javac and a run
script.
Even if you do get blue with the different ClassLoaders for Printer and
CustomSquare, I would probably argue that this is incorrect but I have
to admit that this argument could be because I've misunderstood the
meaning of 'runtime package' in terms of package private accessibility
in the JVM spec.
Jeff
On Tue, 2009-04-14 at 15:30 -0400, Karen Kinnear wrote:
> Jeff,
>
> Perhaps you can help me duplicate the problem.
>
> First - what does java -version say?
>
> I took the source code appended, and modified the URL setting,
> which I believe should just give me your second example, i.e.
> CustomSquare instantiated in a different ClassLoader than Printer.
>
> When I run this with Sun's 1.6 or recent 1.7 I get "blue".
>
> What did we do differently?
>
> thanks,
> Karen
>
> Jeffrey Sinclair wrote:
> > hotspot-dev,
> >
> > I've been struggling to understand why HotSpot does not throw an
> > IllegalAccessError when a call is made to an override of a package
> > private method on an instance loaded by a different class loader. I was
> > hoping someone could explain to me in technical detail where I'm going
> > wrong because it appears to be a bug.
> >
> > (all source code is pasted at the end of the mail)
> >
> > I have a class called Square with a package private method named
> > getColour() which returns 'red'. I have a subclass of Square called
> > CustomSquare which overrides getColour() to return 'blue'. I have
> > another class called Printer which simply prints out getColour() for the
> > Square passed to it. I then have two test cases:
> >
> > * Printer.print(Square) is called with a CustomSquare instantiated in
> > the same ClassLoader as Printer.
> > * Printer.print(Square) is called with a CustomSquare instantiated in
> > a different ClassLoader as Printer.
> >
> > What I find is that I get 'blue' in the first test (as expected) and
> > 'red' in the second test (not expected).
> >
> >>From the Access Control constraints in the Linking section of the JVM
> > specification (5.4.4), I as expecting an IllegalAccessError to be thrown
> > because it states that a package private method is accessible to a class
> > if it is declared by a class in the same runtime package.
> >
> > My understanding is that Printer is not in the same runtime package as
> > CustomSquare which explains why my override does not kick in, but it
> > does not explain why an IllegalAccessError is not thrown.
> >
> > I was wondering if someone could explain the behaviour to me.
> >
> > Regards,
> >
> > Jeff
> >
> > The source code:
> >
> > public class Main {
> > public static void main(String[] args) throws Exception {
> > URL[] urls = new URL[]{new URL("path/to/CustomSquare")};
> > URLClassLoader loader = new URLClassLoader(urls);
> > Class clazz =
> > loader.loadClass("uk.co.cooljeff.visibility.CustomSquare");
> > Printer printer = new Printer();
> > printer.print((Square)clazz.newInstance()); // 'red' gets printed
> > }
> > }
> >
> > package uk.co.cooljeff.visibility;
> >
> > public class Printer {
> > public void print(Square square) {
> > System.out.println(square.getColour());
> > }
> > }
> >
> > package uk.co.cooljeff.visibility;
> >
> > public class CustomSquare extends Square {
> > public CustomSquare() {
> > super(5);
> > }
> >
> > @Override
> > public String getColour() {
> > return "blue";
> > }
> > }
> >
> > package uk.co.cooljeff.visibility;
> >
> > public class Square {
> > private float length;
> >
> > public Square(float length) {
> > this.length = length;
> > }
> >
> > public float calculateArea() {
> > return length * length;
> > }
> >
> > String getColour() {
> > return "red";
> > }
> > }
> >
>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: DefaultVisibilityOverride.zip
Type: application/zip
Size: 12621 bytes
Desc: not available
Url : http://mail.openjdk.java.net/pipermail/hotspot-dev/attachments/20090414/c36696e9/attachment.zip
More information about the hotspot-dev
mailing list