invokevirtual on package private override in different classloader

Jeffrey Sinclair jeff at cooljeff.co.uk
Sat Apr 18 09:32:35 PDT 2009


Karen,

Please find attached a zip file which packages the example up with a
build script that uses javac and a plain old run script.

Simply run build.sh followed by run.sh (assumes that javac and java are
on the PATH).

Regards,

Jeff

On Thu, 2009-04-16 at 17:42 -0400, Karen Kinnear wrote:
> 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>
> 
-------------- next part --------------
A non-text attachment was scrubbed...
Name: PackagePrivateIssue.zip
Type: application/zip
Size: 17900 bytes
Desc: not available
Url : http://mail.openjdk.java.net/pipermail/hotspot-dev/attachments/20090418/6517368f/attachment.zip 


More information about the hotspot-dev mailing list