invokevirtual on package private override in different classloader

Karen Kinnear Karen.Kinnear at Sun.COM
Thu Apr 16 14:42:32 PDT 2009


Jeff,

Thank you for sending me this information. I have a theory, but I
would be much more comfortable running the test first. I have  
experimented
with this, but I'd feel much more comfortable duplicating your results.

I do appreciate you offering to package this up using plain old javac/  
and
a run script - I don't have Eclipse installed and much as I've heard it
is a great product, I don't have the cycles to do that in the near  
future.

thanks so much,
Karen

On Apr 14, 2009, at 5:33 PM, Jeffrey Sinclair wrote:

> 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";
>>>  }
>>> }
>>>
>>
> <DefaultVisibilityOverride.zip>




More information about the hotspot-dev mailing list