1 2 /* 3 4 The author of this software is Ian Kaplan 5 Bear Products International 6 www.bearcave.com 7 iank@bearcave.com 8 9 Copyright (c) Ian Kaplan, 1999, 2000 10 11 See copyright file for usage and licensing 12 13 */ 14 15 package attr; 16 17 import java.io.*; 18 import util.*; 19 import jconst.*; 20 21 /** 22 23 <p> 24 This object represents the Java class file inner class 25 information. 26 27 <p> 28 Inner classes were added to Java 1.1 and are described by 29 Sun's Inner Class Specification, 2/10/97. 30 31 <p> 32 An inner class is a class that is nested inside another class. The 33 inner class exists in the local scope of its enclosing class. So 34 an inner class may access any class variables or member functions 35 of the parent class. It may also reference any visible methods 36 from the parent classes super class. 37 38 <p> 39 Although the inner class shares scoping with its parent class, it 40 is compiled into a separate class file. This class has a name that 41 is created from the inner class and its parent class. To quote the 42 Inner class specification (Class Name Transformations): 43 44 <blockquote> 45 Names of nested classes are transformed as necessary by the 46 compiler to avoid conflicts with identical names in other 47 scopes. Names are encoded to the virtual machine by taking their 48 source form, qualified with dots, and changing each dot after a 49 class name into a dollar sign. 50 </blockquote> 51 52 <p> 53 The JVM has no special support for inner classes. They are 54 supported in the compiler by allowing inner class methods to 55 reference class variables and methods that might not normally be in 56 scope for an external class. To quote Sun's inner class 57 specification "This complicates the compiler's job." 58 59 <p> 60 The format for the inner classes attribute is: 61 62 <pre> 63 innerClasses_attribute { 64 u2 attribute_name_index; 65 u4 attribute_name_length; 66 u2 number_of_classes 67 innerClassInfo classes[ number_of_classes]; 68 } 69 </pre> 70 71 <p> 72 The attribute_name_index and attribute length are read by the 73 attrFactory.allocAttr method. These values are passed into the class 74 constructor. 75 76 <p> 77 Here innerClassInfo is 78 79 <pre> 80 innerClassInfo { 81 u2 inner_class_info_index; 82 u2 outer_class_info_index; 83 u2 inner_name_index; 84 u2 inner_class_access_flags; 85 } 86 </pre> 87 88 <p> 89 Sun's JVM Specification and inner class specification is difficult 90 to understand when it comes to inner classes. 91 92 <p> 93 The inner_class_info_index is either zero or an index into the 94 constant table for a constClass_or_String representing the 95 inner class. 96 97 <p> 98 The outer_class_info_index is zero if the inner_class is not a 99 member. Otherwise the value of outer_class_info_index is an index 100 into the constant table for a constClass_or_String representing the 101 class or interface of which the inner_class is a member. 102 103 <p> 104 If the inner_class is anonymous, the inner_name_index will be 105 zero. Otherwise this is an index into the constant table for 106 a constUtf8 object which contains the class name. 107 108 <p> 109 The inner_class_access_flags are the access mask for the inner 110 class or interface. 111 112 */ 113 public class inninnerClassAttrtends attrInfo { 114 115 116 class innerClassInfo { 117 constClass_or_String innerClass = null; 118 constClass_or_String outerClass = null; 119 constUtf8 className = null; 120 int accessFlags; 121 122 123 innerClassInfo( DataInputStream dStream, constPool constPoolSec ) { 124 125 int inner_class_info_index = readU2( dStream ); 126 int outer_class_info_index = readU2( dStream ); 127 int inner_name_index = readU2( dStream ); 128 accessFlags = readU2( dStream ); 129 constBase obj; 130 131 if (inner_class_info_index > 0) { 132 obj = constPoolSec.constPoolElem( inner_class_info_index ); 133 if (obj != null && obj instanceof constClass_or_String) { 134 innerClass = (constClass_or_String)obj; 135 } 136 } 137 138 if (outer_class_info_index > 0) { 139 obj = constPoolSec.constPoolElem( outer_class_info_index ); 140 if (obj != null && obj instanceof constClass_or_String) { 141 outerClass = (constClass_or_String)obj; 142 } 143 } 144 145 if (inner_name_index > 0) { 146 obj = constPoolSec.constPoolElem( inner_name_index ); 147 if (obj != null && obj instanceof constUtf8) { 148 className = (constUtf8)obj; 149 } 150 } 151 152 } // innerClassInfo constructor 153 154 155 void pr() { 156 System.out.print("innerClass: "); 157 innerClass.pr(); 158 System.out.print("outerClass: "); 159 outerClass.pr(); 160 } // pr 161 162 } // class innderClassInfo 163 164 165 innerClassInfo classInfoTab[] = null; 166 167 168 public innerClassAttr( String name, int length, 169 DataInputStream dStream, constPool constPoolSec ) { 170 171 int numInnerClasses = readU2( dStream ); 172 if (numInnerClasses > 0) { 173 174 classInfoTab = new innerClassInfo[ numInnerClasses ]; 175 176 for (int i = 0; i < numInnerClasses; i++) { 177 classInfoTab[i] = new innerClassInfo( dStream, constPoolSec ); 178 } 179 } 180 } // innerClassAttr constructor 181 182 } // innerClassAttr 183