Source code: com/techtrader/modules/tools/bytecode/visitor/PrettyPrintVisitor.java
1 package com.techtrader.modules.tools.bytecode.visitor;
2
3
4 import java.io.PrintWriter;
5 import java.io.File;
6 import java.io.IOException;
7
8 import com.techtrader.modules.tools.bytecode.*;
9 import com.techtrader.modules.tools.bytecode.lowlevel.*;
10
11
12 /**
13 * Visitor type that outputs a detailed, formatted document of the
14 * visited entity; similar to the <i>javap -c</i> command but more detailed.
15 *
16 * @author Abe White
17 */
18 public class PrettyPrintVisitor
19 extends BCVisitor
20 implements Constants
21 {
22 private PrintWriter _out = null;
23 private String _prefix = "";
24 private int _entryCount = 0;
25
26
27 /**
28 * Invoke with the class or file names to pretty print; the
29 * functionality is similar to the <i>javap -c</i> command, but more
30 * detailed.
31 */
32 public static void main (String[] args)
33 throws ClassNotFoundException, IOException
34 {
35 if (args.length == 0)
36 {
37 System.err.println ("Usage: PrettyPrintVisitor <classname>+");
38 System.exit (1);
39 }
40
41 PrettyPrintVisitor ppv = new PrettyPrintVisitor ();
42 BCClass type;
43 for (int i = 0; i < args.length; i++)
44 {
45 if (args[i].endsWith (".class"))
46 type = new BCClass (new File (args[i]));
47 else
48 type = new BCClass (Class.forName (args[i]));
49 ppv.visit (type);
50 }
51 }
52
53
54 /**
55 * Constructor; all pritning will go to stdout.
56 */
57 public PrettyPrintVisitor ()
58 {
59 _out = new PrintWriter (System.out);
60 }
61
62
63 /**
64 * Constructor.
65 *
66 * @param out the stream to print to
67 */
68 public PrettyPrintVisitor (PrintWriter out)
69 {
70 _out = out;
71 }
72
73
74 public void visit (VisitAcceptor entity)
75 {
76 super.visit (entity);
77 _out.flush ();
78 }
79
80
81 public void enterBCClass (BCClass obj)
82 {
83 openBlock ("Class");
84
85 println ("magic=" + obj.getMagic ());
86 println ("minor=" + obj.getMinorVersion ());
87 println ("major=" + obj.getMajorVersion ());
88 println ("access=" + obj.getAccessFlags ());
89 println ("name=" + obj.getIndex () + " <" + obj.getName () + ">");
90 println ("super=" + obj.getSuperclassIndex ()
91 + " <" + obj.getSuperclassName () + ">");
92
93 int[] indexes = obj.getInterfaceIndexes ();
94 String[] names = obj.getInterfaceNames ();
95 for (int i = 0; i < indexes.length; i++)
96 println ("interface=" + indexes[i] + " <" + names[i] + ">");
97 }
98
99
100 public void exitBCClass (BCClass obj)
101 {
102 closeBlock ();
103 }
104
105
106 public void enterBCField (BCField obj)
107 {
108 openBlock ("Field");
109 println ("access=" + obj.getAccessFlags ());
110 println ("name=" + obj.getNameIndex () + " <" + obj.getName () + ">");
111 println ("descriptor=" + obj.getDescriptorIndex ()
112 + " <" + obj.getTypeName () + ">");
113 }
114
115
116 public void exitBCField (BCField obj)
117 {
118 closeBlock ();
119 }
120
121
122 public void enterBCMethod (BCMethod obj)
123 {
124 openBlock ("Method");
125 println ("access=" + obj.getAccessFlags ());
126 println ("name=" + obj.getNameIndex () + " <" + obj.getName () + ">");
127 println ("descriptor=" + obj.getDescriptorIndex ());
128 println ("return=" + obj.getReturnTypeName ());
129 String[] params = obj.getParamTypeNames ();
130 for (int i = 0; i < params.length; i++)
131 println ("param=" + params[i]);
132 }
133
134
135 public void exitBCMethod (BCMethod obj)
136 {
137 closeBlock ();
138 }
139
140
141 public void enterAttribute (Attribute obj)
142 {
143 openBlock (obj.getName ());
144 }
145
146
147 public void exitAttribute (Attribute obj)
148 {
149 closeBlock ();
150 }
151
152
153 public void enterConstantValueAttribute (ConstantValueAttribute obj)
154 {
155 println ("value=" + obj.getValueIndex () + " <" + obj.getTypeName ()
156 + "=" + obj.getValue () + ">");
157 }
158
159
160 public void enterExceptionsAttribute (ExceptionsAttribute obj)
161 {
162 int[] indexes = obj.getExceptionIndexes ();
163 String[] names = obj.getExceptionTypeNames ();
164 for (int i = 0; i < indexes.length; i++)
165 println ("exception=" + indexes[i] + " <" + names[i] + ">");
166 }
167
168
169 public void enterSourceFileAttribute (SourceFileAttribute obj)
170 {
171 println ("source=" + obj.getSourceFileIndex () + " <"
172 + obj.getSourceFile () + ">");
173 }
174
175
176 public void enterUnknownAttribute (UnknownAttribute obj)
177 {
178 println ("value=" + new String (obj.getValue ()));
179 new Exception ().printStackTrace ();
180 }
181
182
183 public void enterCode (Code obj)
184 {
185 println ("maxStack=" + obj.getMaxStack ());
186 println ("maxLocals=" + obj.getMaxLocals ());
187 println ("");
188 }
189
190
191 public void enterExceptionHandler (ExceptionHandler obj)
192 {
193 openBlock ("ExceptionHandler");
194 println ("startPc=" + obj.getStartPc ());
195 println ("endPc=" + obj.getEndPc ());
196 println ("handlerPc=" + obj.getHandlerPc ());
197 println ("catch=" + obj.getCatchTypeIndex () + " <"
198 + obj.getCatchTypeName () + ">");
199 }
200
201
202 public void exitExceptionHandler (ExceptionHandler obj)
203 {
204 closeBlock ();
205 }
206
207
208 public void enterInnerClass (InnerClass obj)
209 {
210 openBlock ("InnerClass");
211 println ("access=" + obj.getAccessFlags ());
212 println ("name=" + obj.getNameIndex () + " <" + obj.getName () + ">");
213 println ("index=" + obj.getIndex ());
214 println ("outer=" + obj.getOuterClassIndex ());
215 }
216
217
218 public void exitInnerClass (InnerClass obj)
219 {
220 closeBlock ();
221 }
222
223
224 public void enterLineNumber (LineNumber obj)
225 {
226 openBlock ("LineNumber");
227 println ("startPc=" + obj.getStartPc ());
228 println ("line=" + obj.getLineNumber ());
229 }
230
231
232 public void exitLineNumber (LineNumber obj)
233 {
234 closeBlock ();
235 }
236
237
238 public void enterLocalVariable (LocalVariable obj)
239 {
240 openBlock ("LocalVariable");
241 println ("startPc=" + obj.getStartPc ());
242 println ("length=" + obj.getLength ());
243 println ("index=" + obj.getIndex ());
244 println ("name=" + obj.getNameIndex () + " <" + obj.getName () + ">");
245 println ("descriptor=" + obj.getDescriptorIndex ()
246 + " <" + obj.getTypeName () + ">");
247 }
248
249
250 public void exitLocalVariable (LocalVariable obj)
251 {
252 closeBlock ();
253 }
254
255
256 public void enterInstruction (Instruction obj)
257 {
258 _out.print (_prefix + obj.getByteIndex () + " " + obj.getName () + " ");
259 }
260
261
262 public void exitInstruction (Instruction obj)
263 {
264 _out.println ();
265 }
266
267
268 public void enterClassInstruction (ClassInstruction obj)
269 {
270 _out.print (obj.getClassIndex () + " <" + obj.getClassName () + ">");
271 }
272
273
274 public void enterConstantInstruction (ConstantInstruction obj)
275 {
276 switch (obj.getOpCode ())
277 {
278 case BIPUSH:
279 case SIPUSH:
280 case LDC:
281 case LDC_W:
282 case LDC2_W:
283 _out.print (obj.getConstant ().toString ());
284 }
285 }
286
287
288 public void enterGetFieldInstruction (GetFieldInstruction obj)
289 {
290 _out.print (obj.getFieldIndex () + " <" + obj.getFieldOwnerTypeName ()
291 + "." + obj.getFieldName () + ">");
292 }
293
294
295 public void enterIIncInstruction (IIncInstruction obj)
296 {
297 _out.print (obj.getIndex () + " ");
298 if (obj.getIncrement () > 0)
299 _out.print ("+");
300 _out.print (obj.getIncrement ());
301 }
302
303
304 public void enterJumpInstruction (JumpInstruction obj)
305 {
306 _out.print (obj.getOffset ());
307 }
308
309
310 public void enterLoadInstruction (LoadInstruction obj)
311 {
312 switch (obj.getOpCode ())
313 {
314 case ILOAD:
315 case LLOAD:
316 case FLOAD:
317 case DLOAD:
318 case ALOAD:
319 _out.print (obj.getIndex ());
320 }
321 }
322
323
324 public void enterLookupSwitchInstruction (LookupSwitchInstruction obj)
325 {
326 _out.println ();
327 _prefix += " ";
328
329 int[] offsets = obj.getOffsets ();
330 int[] matches = obj.getMatches ();
331 for (int i = 0; i < offsets.length; i++)
332 println ("case " + matches[i] + "=" + offsets[i]);
333 _out.print (_prefix + "default=" + obj.getDefaultOffset ());
334
335 _prefix = _prefix.substring (2);
336 }
337
338
339 public void enterMethodInstruction (MethodInstruction obj)
340 {
341 _out.print (obj.getMethodIndex () + " <" + obj.getMethodOwnerTypeName ()
342 + "." + obj.getMethodName () + "(");
343 String[] params = obj.getMethodParamTypeNames ();
344 int dotIndex;
345 for (int i = 0; i < params.length; i++)
346 {
347 dotIndex = params[i].lastIndexOf ('.');
348 if (dotIndex != -1)
349 params[i] = params[i].substring (dotIndex + 1);
350
351 _out.print (params[i]);
352 if (i != params.length - 1)
353 _out.print (", ");
354 }
355
356 _out.print (")>");
357 }
358
359
360 public void enterMultiANewArrayInstruction (MultiANewArrayInstruction obj)
361 {
362 _out.print (obj.getClassIndex () + " " + obj.getDimensions ()
363 + " <" + obj.getClassName ());
364 String post = "";
365 for (int i = 0; i < obj.getDimensions (); i++)
366 post += "[]";
367 _out.print (post + ">");
368 }
369
370
371 public void enterNewArrayInstruction (NewArrayInstruction obj)
372 {
373 _out.print (obj.getArrayTypeCode () + " <"
374 + obj.getArrayTypeName () + "[]>");
375 }
376
377
378 public void enterPutFieldInstruction (PutFieldInstruction obj)
379 {
380 _out.print (obj.getFieldIndex () + " <" + obj.getFieldOwnerTypeName ()
381 + "." + obj.getFieldName () + ">");
382 }
383
384
385 public void enterRetInstruction (RetInstruction obj)
386 {
387 _out.print (obj.getIndex ());
388 }
389
390
391 public void enterStoreInstruction (StoreInstruction obj)
392 {
393 switch (obj.getOpCode ())
394 {
395 case ISTORE:
396 case LSTORE:
397 case FSTORE:
398 case DSTORE:
399 case ASTORE:
400 _out.print (obj.getIndex ());
401 }
402 }
403
404
405 public void enterTableSwitchInstruction (TableSwitchInstruction obj)
406 {
407 _out.println ();
408 _prefix += " ";
409
410 println ("low=" + obj.getLow ());
411 println ("high=" + obj.getHigh ());
412 int[] offsets = obj.getOffsets ();
413 for (int i = 0; i < offsets.length; i++)
414 println ("case=" + offsets[i]);
415 _out.print (_prefix + "default=" + obj.getDefaultOffset ());
416
417 _prefix = _prefix.substring (2);
418 }
419
420
421 public void enterWideInstruction (WideInstruction obj)
422 {
423 int ins = obj.getInstruction ();
424 _out.print (ins + " <" + OPCODE_NAMES[ins] + ">");
425 }
426
427
428 public void enterConstantPool (ConstantPool obj)
429 {
430 _entryCount = 0;
431 openBlock ("ConstantPool");
432 }
433
434
435 public void exitConstantPool (ConstantPool obj)
436 {
437 closeBlock ();
438 }
439
440
441 public void enterEntry (Entry obj)
442 {
443 String name = obj.getClass ().getName ();
444 openBlock (++_entryCount + ": "
445 + name.substring (name.lastIndexOf ('.') + 1));
446 }
447
448
449 public void exitEntry (Entry obj)
450 {
451 closeBlock ();
452 }
453
454
455 public void enterClassEntry (ClassEntry obj)
456 {
457 println ("name=" + obj.getNameIndex ());
458 }
459
460
461 public void enterDoubleEntry (DoubleEntry obj)
462 {
463 println ("value=" + obj.getValue ());
464 }
465
466
467 public void enterFieldEntry (FieldEntry obj)
468 {
469 println ("class=" + obj.getClassIndex ());
470 println ("nameAndType=" + obj.getNameAndTypeIndex ());
471 }
472
473
474 public void enterFloatEntry (FloatEntry obj)
475 {
476 println ("value=" + obj.getValue ());
477 }
478
479
480 public void enterIntEntry (IntEntry obj)
481 {
482 println ("value=" + obj.getValue ());
483 }
484
485
486 public void enterInterfaceMethodEntry (InterfaceMethodEntry obj)
487 {
488 println ("class=" + obj.getClassIndex ());
489 println ("nameAndType=" + obj.getNameAndTypeIndex ());
490 }
491
492
493 public void enterLongEntry (LongEntry obj)
494 {
495 println ("value=" + obj.getValue ());
496 }
497
498
499 public void enterMethodEntry (MethodEntry obj)
500 {
501 println ("class=" + obj.getClassIndex ());
502 println ("nameAndType=" + obj.getNameAndTypeIndex ());
503 }
504
505
506 public void enterNameAndTypeEntry (NameAndTypeEntry obj)
507 {
508 println ("name=" + obj.getNameIndex ());
509 println ("descriptor=" + obj.getDescriptorIndex ());
510 }
511
512
513 public void enterStringEntry (StringEntry obj)
514 {
515 println ("index=" + obj.getStringIndex ());
516 }
517
518
519 public void enterUTF8Entry (UTF8Entry obj)
520 {
521 println ("value=" + obj.getValue ());
522 }
523
524
525 private void println (String ln)
526 {
527 _out.print (_prefix);
528 _out.println (ln);
529 }
530
531
532 private void openBlock (String name)
533 {
534 println (name + " {");
535 _prefix += " ";
536 }
537
538
539 private void closeBlock ()
540 {
541 _prefix = _prefix.substring (2);
542 println ("}");
543 }
544 }