McQueeney.com
 

Tom's Blog

"Synthetic" accessors when using inner classes
Published by Tom | July 20, 2004 01:24 PM EDT |

Today, I enabled Eclipse to warn me when my code accesses a "non-accessible member of an enclosing type" and learned something in the process.

From what I gather, code like the following:

public class OuterClass {

    /** A log4j Logger. */
    private static final Logger LOG = 
        Logger.getLogger(OuterClass.class);

    // ... Methods defined for OuterClass
    

    private class InnerClass {
        InnerClass() {
            LOG.debug("Created an instance of InnerClass");
        }
    }
}

causes the compiler to generate a package-private "synthetic" accessor method inside OuterClass to allow InnerClass to see the private LOG instance. From what I read, it seems since the inner class is compiled to a separate .class file, the runtime needs some way for inner class instances to access the private members of the outer class. Syntactically, and according to the Java Language Specification, non-static inner classes are allowed to access private variables and methods in outer classes. But how do those inner-class instances access the private fields and methods?

The solution most Java compilers seem to implement is to add extra (the JLS calls them "synthetic") package-private accessors to the outer class to allow the inner classes to see the private information.

My inner class in question is a private custom Iterator that I don't want others accessing directly. When I compiled the class in Eclipse with the "Access to a non-accessible member of an enclosing type" set to "Warning" (Window > Preferences > Java > Compiler > Advanced), it warned me that "Read access to enclosing field OuterClass.LOG is emulated by a synthetic accessor method. Increasing its visibility will improve your performance." So I searched around to find out what all this meant, starting my journey.

My search led first to this blog entry from Vladimir Roubtsov. That led me to an archived discussion of the topic from the ADVANCED-JAVA@DISCUSS.DEVELOP.COM mailing list to help shed more light on the subject. Vladimar's blog also references a discussion on this topic on the Eclipse cdt-dev mailing list, but it requires you to sign up to read that archived discussion. That discussion might delve further into what performance penalty you might pay by accessing the private members via generated accessors.

Since I don't want to increase the visibility of the private fields in my outer class, I'm going to live with any performance hit rather than break encapsulation.


20040720 Tuesday July 20, 2004 Permalink Comments [3]
Comments:

Actually, the warning Eclipse generates is kind of misleading. Perhaps you get a performance hit, but what's worse is that the private member is no longer private since a package-private accessor is generated. This can lead to security problems, for example.

As a workaround, why not just use another logger in your private inner class?

Posted by Maik on July 20, 2004 at 07:05 PM EDT
Website: http://www.blizzy.de #

Good point about using another Logger. However, my actual inner class also uses a private method in the outer class as well as the shared logger. I left that part out to keep my example simple. And you are right about the synthetic getter violating encapsulation. A malicious user of such a class could examine the bytecode, determine the name of the generated package-private method, and be able then to access a private member variable. That's not the way Java is supposed to work, but apparently it is allowed. My solution, since security isn't an issue, was not to deliberately violate encapsulation by providing an accessor to the private members. The compiler will provide such access to violate encapsulation, but I'm not going to help it along.

Posted by Tom McQueeney on July 20, 2004 at 10:43 PM EDT
Website: http://mcqueeney.com #

I don't see any performance hit. Am I missing something? Here is the test code I tried to measure the performance: http://rafb.net/paste/results/ytClc214.html

Posted by Trustin Lee on March 23, 2005 at 01:52 PM EST #

Comments are closed for this entry.