Thu, 30 Jul 2009 09:18:55 -0700
4880672: javap does not output inner interfaces of an interface
Reviewed-by: mcimadamore
1 /*
2 * Copyright 2007-2008 Sun Microsystems, Inc. All Rights Reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
26 package com.sun.tools.javap;
28 import java.util.ArrayList;
29 import java.util.List;
31 import com.sun.tools.classfile.AccessFlags;
32 import com.sun.tools.classfile.Code_attribute;
33 import com.sun.tools.classfile.ConstantPool;
34 import com.sun.tools.classfile.ConstantPoolException;
35 import com.sun.tools.classfile.DescriptorException;
36 import com.sun.tools.classfile.Instruction;
37 import com.sun.tools.classfile.Instruction.TypeKind;
38 import com.sun.tools.classfile.Method;
40 /*
41 * Write the contents of a Code attribute.
42 *
43 * <p><b>This is NOT part of any API supported by Sun Microsystems. If
44 * you write code that depends on this, you do so at your own risk.
45 * This code and its internal interfaces are subject to change or
46 * deletion without notice.</b>
47 */
48 class CodeWriter extends BasicWriter {
49 static CodeWriter instance(Context context) {
50 CodeWriter instance = context.get(CodeWriter.class);
51 if (instance == null)
52 instance = new CodeWriter(context);
53 return instance;
54 }
56 protected CodeWriter(Context context) {
57 super(context);
58 context.put(CodeWriter.class, this);
59 attrWriter = AttributeWriter.instance(context);
60 classWriter = ClassWriter.instance(context);
61 constantWriter = ConstantWriter.instance(context);
62 sourceWriter = SourceWriter.instance(context);
63 tryBlockWriter = TryBlockWriter.instance(context);
64 stackMapWriter = StackMapWriter.instance(context);
65 localVariableTableWriter = LocalVariableTableWriter.instance(context);
66 localVariableTypeTableWriter = LocalVariableTypeTableWriter.instance(context);
67 typeAnnotationWriter = TypeAnnotationWriter.instance(context);
68 options = Options.instance(context);
69 }
71 void write(Code_attribute attr, ConstantPool constant_pool) {
72 println(" Code:");
73 writeVerboseHeader(attr, constant_pool);
74 writeInstrs(attr);
75 writeExceptionTable(attr);
76 attrWriter.write(attr, attr.attributes, constant_pool);
77 }
79 public void writeVerboseHeader(Code_attribute attr, ConstantPool constant_pool) {
80 Method method = classWriter.getMethod();
81 String argCount;
82 try {
83 int n = method.descriptor.getParameterCount(constant_pool);
84 if (!method.access_flags.is(AccessFlags.ACC_STATIC))
85 ++n; // for 'this'
86 argCount = Integer.toString(n);
87 } catch (ConstantPoolException e) {
88 argCount = report(e);
89 } catch (DescriptorException e) {
90 argCount = report(e);
91 }
93 println(" Stack=" + attr.max_stack +
94 ", Locals=" + attr.max_locals +
95 ", Args_size=" + argCount);
97 }
99 public void writeInstrs(Code_attribute attr) {
100 List<InstructionDetailWriter> detailWriters = getDetailWriters(attr);
102 for (Instruction instr: attr.getInstructions()) {
103 try {
104 for (InstructionDetailWriter w: detailWriters)
105 w.writeDetails(instr);
106 writeInstr(instr);
107 } catch (ArrayIndexOutOfBoundsException e) {
108 println(report("error at or after byte " + instr.getPC()));
109 break;
110 }
111 }
113 for (InstructionDetailWriter w: detailWriters)
114 w.flush();
115 }
117 public void writeInstr(Instruction instr) {
118 print(" " + instr.getPC() + ":\t");
119 print(instr.getMnemonic());
120 instr.accept(instructionPrinter, null);
121 println();
122 }
123 // where
124 Instruction.KindVisitor<Void,Void> instructionPrinter =
125 new Instruction.KindVisitor<Void,Void>() {
127 public Void visitNoOperands(Instruction instr, Void p) {
128 return null;
129 }
131 public Void visitArrayType(Instruction instr, TypeKind kind, Void p) {
132 print(" " + kind.name);
133 return null;
134 }
136 public Void visitBranch(Instruction instr, int offset, Void p) {
137 print("\t" + (instr.getPC() + offset));
138 return null;
139 }
141 public Void visitConstantPoolRef(Instruction instr, int index, Void p) {
142 print("\t#" + index + "; //");
143 printConstant(index);
144 return null;
145 }
147 public Void visitConstantPoolRefAndValue(Instruction instr, int index, int value, Void p) {
148 print("\t#" + index + ", " + value + "; //");
149 printConstant(index);
150 return null;
151 }
153 public Void visitLocal(Instruction instr, int index, Void p) {
154 print("\t" + index);
155 return null;
156 }
158 public Void visitLocalAndValue(Instruction instr, int index, int value, Void p) {
159 print("\t" + index + ", " + value);
160 return null;
161 }
163 public Void visitLookupSwitch(Instruction instr, int default_, int npairs, int[] matches, int[] offsets) {
164 int pc = instr.getPC();
165 print("{ //" + npairs);
166 for (int i = 0; i < npairs; i++) {
167 print("\n\t\t" + matches[i] + ": " + (pc + offsets[i]) + ";");
168 }
169 print("\n\t\tdefault: " + (pc + default_) + " }");
170 return null;
171 }
173 public Void visitTableSwitch(Instruction instr, int default_, int low, int high, int[] offsets) {
174 int pc = instr.getPC();
175 print("{ //" + low + " to " + high);
176 for (int i = 0; i < offsets.length; i++) {
177 print("\n\t\t" + (low + i) + ": " + (pc + offsets[i]) + ";");
178 }
179 print("\n\t\tdefault: " + (pc + default_) + " }");
180 return null;
181 }
183 public Void visitValue(Instruction instr, int value, Void p) {
184 print("\t" + value);
185 return null;
186 }
188 public Void visitUnknown(Instruction instr, Void p) {
189 return null;
190 }
191 };
194 public void writeExceptionTable(Code_attribute attr) {
195 if (attr.exception_table_langth > 0) {
196 println(" Exception table:");
197 println(" from to target type");
198 for (int i = 0; i < attr.exception_table.length; i++) {
199 Code_attribute.Exception_data handler = attr.exception_table[i];
200 printFixedWidthInt(handler.start_pc, 6);
201 printFixedWidthInt(handler.end_pc, 6);
202 printFixedWidthInt(handler.handler_pc, 6);
203 print(" ");
204 int catch_type = handler.catch_type;
205 if (catch_type == 0) {
206 println("any");
207 } else {
208 print("Class ");
209 println(constantWriter.stringValue(catch_type));
210 println("");
211 }
212 }
213 }
215 }
217 private void printConstant(int index) {
218 constantWriter.write(index);
219 }
221 private void printFixedWidthInt(int n, int width) {
222 String s = String.valueOf(n);
223 for (int i = s.length(); i < width; i++)
224 print(" ");
225 print(s);
226 }
228 private List<InstructionDetailWriter> getDetailWriters(Code_attribute attr) {
229 List<InstructionDetailWriter> detailWriters =
230 new ArrayList<InstructionDetailWriter>();
231 if (options.details.contains(InstructionDetailWriter.Kind.SOURCE)) {
232 sourceWriter.reset(classWriter.getClassFile(), attr);
233 detailWriters.add(sourceWriter);
234 }
236 if (options.details.contains(InstructionDetailWriter.Kind.LOCAL_VARS)) {
237 localVariableTableWriter.reset(attr);
238 detailWriters.add(localVariableTableWriter);
239 }
241 if (options.details.contains(InstructionDetailWriter.Kind.LOCAL_VAR_TYPES)) {
242 localVariableTypeTableWriter.reset(attr);
243 detailWriters.add(localVariableTypeTableWriter);
244 }
246 if (options.details.contains(InstructionDetailWriter.Kind.STACKMAPS)) {
247 stackMapWriter.reset(attr);
248 stackMapWriter.writeInitialDetails();
249 detailWriters.add(stackMapWriter);
250 }
252 if (options.details.contains(InstructionDetailWriter.Kind.TRY_BLOCKS)) {
253 tryBlockWriter.reset(attr);
254 detailWriters.add(tryBlockWriter);
255 }
257 if (options.details.contains(InstructionDetailWriter.Kind.TYPE_ANNOS)) {
258 typeAnnotationWriter.reset(attr);
259 detailWriters.add(typeAnnotationWriter);
260 }
262 return detailWriters;
263 }
265 private AttributeWriter attrWriter;
266 private ClassWriter classWriter;
267 private ConstantWriter constantWriter;
268 private LocalVariableTableWriter localVariableTableWriter;
269 private LocalVariableTypeTableWriter localVariableTypeTableWriter;
270 private TypeAnnotationWriter typeAnnotationWriter;
271 private SourceWriter sourceWriter;
272 private StackMapWriter stackMapWriter;
273 private TryBlockWriter tryBlockWriter;
274 private Options options;
275 }