Contents | Prev | Next Inner Classes Specification


What are the new binary compatibility requirements for Java 1.1 classes?

In order to binary ensure compatibility between bytecodes output for Java 1.1 compilers from different vendors, and to ensure proper applicability of debuggers and similar tools to those bytecodes, Java makes certain requirements on the form of the bytecodes produced. This section describes the requirements, new in Java 1.1, which pertain to the implementation of various kinds of inner and nested top-level classes.

Bytecode names of classes and interfaces

Instances of the Java Virtual Machines, and Java bytecodes, refer to reference types by means of bytecode names which differ in detail from the names used in Java source code. The bytecode name of a package member T is defined as the name of the package, with every `.' replaced by `/', followed (if the package name is not null) by another `/', and then by the simple name of T. The bytecode name of T also serves as a prefix for the bytecode name of every class defined within the body of T.

The bytecode name of a class C which is a non-private member of another class, and which is not contained (directly or indirectly) in any block or private class, is defined as the bytecode name of the immediately-enclosing class, followed by `$', followed by the simple name of C.

All other classes are called inaccessible. No inaccessible class N can ever be referenced by the code of any other compilation unit. Thus, as long as the name of N is chosen by the compiler in such as way as not to conflict with any other class in the same compilation unit, the name will be globally unique, because (as required previously) its prefix is unique to the package member in which it occurs.

For the sake of tools, there are some additional requirements on the naming of an inaccessible class N. Its bytecode name must consist of the bytecode name of an enclosing class (the immediately enclosing class, if it is a member), followed either by `$' and a positive decimal numeral chosen by the compiler, or by `$' and the simple name of N, or else by both (in that order). Moreover, the bytecode name of a block-local N must consist of its enclosing package member T, the characters `$1$', and N, if the resulting name would be unique.

The string produced by the getName method of Class is derived, in all of these cases, from the bytecode name, by replacing `/' by `.'. There is no attempt to "clean up" the name to make it resemble Java source code.

The class attribute InnerClasses

The bytecode output of a Java 1.1 compiler may refer (via CONSTANT_Class entries) to bytecode names of classes or interfaces which are not package members. If so, the bytecodes must also contain an class attribute called InnerClasses which declares the encoding of those names. This attribute contains an array of records, one for each encoded name:

    InnerClasses_attribute {
      u2 attribute_name_index;
      u4 attribute_length;
      u2 number_of_classes;
      {
        u2 inner_class_info_index;   // CONSTANT_Class_info index
        u2 outer_class_info_index;   // CONSTANT_Class_info index
        u2 inner_name_index;         // CONSTANT_Utf8_info index
        u2 inner_class_access_flags; // access_flags bitmask
      } classes[number_of_classes]
    }

Each array element records a class with an encoded name, its defining scope, its simple name, and a bitmask of the originally declared, untransformed access flags. If an inner class is not a member, its outer_class_info_index is zero. If a class is anonymous, its inner_name_index is zero.

If a class C was declared protected, the public access flag bit is cleared in its InnerClasses record, even though it is set in C's access_flags field.

If the outer_class_info_index of a record refers to a class E which itself is not a package member, then an earlier record of the same InnerClasses attribute must describe E.

If a class has members which are types, it must have an InnerClasses attribute, with a record for each of the types. The rules already given imply that a class which is not a package member has an InnerClasses attribute which has a record for it and all of its enclosing classes, except the outermost.

These rules ensure that compilers and debuggers can correctly interpret bytecode names without parsing them, and without opening additional files to examine inner class definitions. Compilers are allowed to omit InnerClasses records for inaccessible classes, but they are encouraged to include records for all classes, especially when the code is being compiled for use with a debugger.

The member attribute Synthetic

As discussed previously, the compiler synthesizes certain hidden fields and methods in order to implement the scoping of names. These fields are private unless noted otherwise, or they are at most of package scope.

Java 1.1 compilers are required, when producing bytecodes, to mark any field or member not directly defined in the source code with an attribute named Synthetic. (At present, the length must be zero.) This will allow other compilers to avoid inadvertant source-level references to non-private hidden members, and will allow tools to avoid displaying them unnecessarily.

(A corresponding mechanism for declaring a local variable to be Synthetic may also be introduced.)

Java 1.1 compilers are strongly encouraged, though not required, to use the following naming conventions when implementing inner classes. Compilers may not use synthetic names of the forms defined here for any other purposes.

A synthetic field pointing to the outermost enclosing instance is named this$0. The next-outermost enclosing instance is this$1, and so forth. (At most one such field is necessary in any given inner class.) A synthetic field containing a copy of a constant v is named val$v. These fields are final.

All these synthetic fields are initialized by constructor parameters, which have the same names as the fields they initialize. If one of the parameters is the innermost enclosing instance, it is the first. All such constructor parameters are deemed to be synthetic. If the compiler determines that the synthetic field's value is used only in the code of the constructor, it may omit the field itself, and use only the parameter to implement variable references.

A non-private final synthetic method which grants access to a private member or constructor has a name of the form access$N, where N is a decimal numeral. The organization of such access protocols is unspecified.

Debuggers and similar tools which are 1.1 compatible must recognize these naming conventions, and organize variable displays and symbol tables accordingly. Note that tools may need to parse these names. Compilers are strongly encouraged to use these conventions, at least by default.

Implementations of the Java Virtual Machine may verify and require that the synthetic members specified here are defined and used properly. It is reasonable to exploit the nature of synthetic members by basing optimization techniques on them.


Contents | Prev | Next

Inner Classes Specification (HTML generated by dkramer on March 15, 1997)
Copyright © 1996, 1997 Sun Microsystems, Inc. All rights reserved
Please send any comments or corrections to john.rose@eng.sun.com