Source Code Cross Referenced for Disassembler.java in  » Scripting » jacl » org » codehaus » janino » tools » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Scripting » jacl » org.codehaus.janino.tools 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * Janino - An embedded Java[TM] compiler
0003:         *
0004:         * Copyright (c) 2006, Arno Unkrig
0005:         * All rights reserved.
0006:         *
0007:         * Redistribution and use in source and binary forms, with or without
0008:         * modification, are permitted provided that the following conditions
0009:         * are met:
0010:         *
0011:         *    1. Redistributions of source code must retain the above copyright
0012:         *       notice, this list of conditions and the following disclaimer.
0013:         *    2. Redistributions in binary form must reproduce the above
0014:         *       copyright notice, this list of conditions and the following
0015:         *       disclaimer in the documentation and/or other materials
0016:         *       provided with the distribution.
0017:         *    3. The name of the author may not be used to endorse or promote
0018:         *       products derived from this software without specific prior
0019:         *       written permission.
0020:         *
0021:         * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
0022:         * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
0023:         * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0024:         * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
0025:         * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
0026:         * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
0027:         * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0028:         * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
0029:         * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
0030:         * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
0031:         * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
0032:         */
0033:
0034:        package org.codehaus.janino.tools;
0035:
0036:        import java.io.*;
0037:        import java.util.*;
0038:
0039:        /**
0040:         * A Java bytecode disassembler, comparable to JAVAP, which is part of
0041:         * Sun's JDK.
0042:         * <p>
0043:         * Notice that this tool does not depend on any other classes or libraries (other than the
0044:         * standard JDK library).
0045:         */
0046:
0047:        public class Disassembler {
0048:            private IndentPrintWriter ipw = new IndentPrintWriter(System.out);
0049:            private boolean verbose = false;
0050:            private File sourceDirectory = new File(".");
0051:
0052:            /**
0053:             * Usage:
0054:             * <pre>
0055:             *   java new.janino.tools.Disassembler [ -o <i>output-file</i> ] [ -help ]
0056:             * </pre>
0057:             * @param args
0058:             * @throws IOException
0059:             */
0060:            public static void main(String[] args) throws IOException {
0061:                Disassembler d = new Disassembler();
0062:                int i;
0063:                for (i = 0; i < args.length; ++i) {
0064:                    String arg = args[i];
0065:                    if (arg.charAt(0) != '-')
0066:                        break;
0067:                    if (arg.equals("-o")) {
0068:                        d.setOut(new FileOutputStream(args[++i]));
0069:                    } else if (arg.equals("-verbose")) {
0070:                        d.setVerbose(true);
0071:                    } else if (arg.equals("-src")) {
0072:                        d.setSourceDirectory(new File(args[++i]));
0073:                    } else if (arg.equals("-help")) {
0074:                        System.out
0075:                                .println("Usage:  java jexpr.Jdisasm [ -o <output-file> ] [ -verbose ] [ -src <source-dir> ] <class-file> ...");
0076:                        System.exit(0);
0077:                    } else {
0078:                        System.err
0079:                                .println("Unrecognized command line option \""
0080:                                        + arg + "\"; try \"-help\".");
0081:                    }
0082:                }
0083:                if (i == args.length) {
0084:                    System.err
0085:                            .println("Class file name missing, try \"-help\".");
0086:                    System.exit(1);
0087:                }
0088:                for (; i < args.length; ++i) {
0089:                    d.disasm(new File(args[i]));
0090:                }
0091:            }
0092:
0093:            public Disassembler() {
0094:            }
0095:
0096:            public void setOut(OutputStream os) {
0097:                this .ipw = new IndentPrintWriter(os);
0098:            }
0099:
0100:            public void setVerbose(boolean verbose) {
0101:                this .verbose = verbose;
0102:            }
0103:
0104:            public void setSourceDirectory(File sourceDirectory) {
0105:                this .sourceDirectory = sourceDirectory;
0106:            }
0107:
0108:            //    void print(byte b)   { this.ipw.print(b); }
0109:            //    void print(short s)  { this.ipw.print(s); }
0110:            void print(int i) {
0111:                this .ipw.print(i);
0112:            }
0113:
0114:            //    void print(long l)   { this.ipw.print(l); }
0115:            //    void print(float f)  { this.ipw.print(f); }
0116:            //    void print(double d) { this.ipw.print(d); }
0117:            void print(String s) {
0118:                this .ipw.print(s);
0119:            }
0120:
0121:            void println() {
0122:                this .ipw.println();
0123:            }
0124:
0125:            void println(String s) {
0126:                this .ipw.println(s);
0127:            }
0128:
0129:            void indent(String s) {
0130:                this .ipw.print(s);
0131:                this .ipw.indent();
0132:            }
0133:
0134:            void indentln(String s) {
0135:                this .ipw.println(s);
0136:                this .ipw.indent();
0137:            }
0138:
0139:            void unindent(String s) {
0140:                this .ipw.unindent();
0141:                this .ipw.print(s);
0142:            }
0143:
0144:            void unindentln(String s) {
0145:                this .ipw.unindent();
0146:                this .ipw.println(s);
0147:            }
0148:
0149:            /**
0150:             * Disassemble one Java<sup>TM</sup> class file to {@link System#out}.
0151:             * 
0152:             * @param file
0153:             * @throws IOException
0154:             */
0155:            public void disasm(File file) throws IOException {
0156:                InputStream is = new FileInputStream(file);
0157:                try {
0158:                    disasm(is);
0159:                } finally {
0160:                    try {
0161:                        is.close();
0162:                    } catch (IOException ex) {
0163:                    }
0164:                }
0165:            }
0166:
0167:            public void disasm(InputStream is) throws IOException {
0168:                this .disasmClassFile(new DataInputStream(is));
0169:                this .println();
0170:                this .ipw.flush();
0171:            }
0172:
0173:            private void disasmClassFile(DataInputStream dis)
0174:                    throws IOException {
0175:                this .indentln("ClassFile {");
0176:                {
0177:                    this .println("magic = 0x"
0178:                            + Integer.toHexString(dis.readInt()));
0179:                    this .println("minor_version = " + dis.readShort());
0180:                    this .println("major_version = " + dis.readShort());
0181:
0182:                    this .constantPool = new ConstantPoolInfo[dis.readShort()];
0183:                    for (short i = 1; i < this .constantPool.length;) {
0184:                        ConstantPoolInfo cpi = readConstantPoolInfo(dis);
0185:                        this .constantPool[i++] = cpi;
0186:                        for (int j = cpi.getSizeInConstantPool(); j > 1; --j) {
0187:                            this .constantPool[i++] = null;
0188:                        }
0189:                    }
0190:                    this .indentln("constant_pool[] = {");
0191:                    {
0192:                        for (short i = 1; i < this .constantPool.length;) {
0193:                            this .print(i + ": ");
0194:                            ConstantPoolInfo cpi = this .constantPool[i];
0195:                            cpi.print(); // Must be invoked only after "this.constantPool" is initialized.
0196:                            this .println();
0197:                            i += cpi.getSizeInConstantPool();
0198:                        }
0199:                    }
0200:                    this .unindentln("}");
0201:
0202:                    this .println("access_flags = "
0203:                            + decodeAccess(dis.readShort()));
0204:
0205:                    short this Class = dis.readShort();
0206:                    this .indent("this_class = " + this Class + " (");
0207:                    {
0208:                        this .printConstantPoolEntry(this Class);
0209:                    }
0210:                    this .unindentln(")");
0211:
0212:                    short super Class = dis.readShort();
0213:                    this .indent("super_class = " + super Class + " (");
0214:                    {
0215:                        this .printConstantPoolEntry(super Class);
0216:                    }
0217:                    this .unindentln(")");
0218:
0219:                    this .indentln("interfaces[] = {");
0220:                    {
0221:                        short interfacesCount = dis.readShort();
0222:                        for (short i = 0; i < interfacesCount; ++i) {
0223:                            this .printConstantPoolEntry(null, dis.readShort());
0224:                            this .println();
0225:                        }
0226:                    }
0227:                    this .unindentln("}");
0228:
0229:                    this .indentln("fields[] = {");
0230:                    {
0231:                        short fieldsCount = dis.readShort();
0232:                        for (short i = 0; i < fieldsCount; ++i) {
0233:                            disasmFieldInfo(dis);
0234:                            this .println();
0235:                        }
0236:                    }
0237:                    this .unindentln("}");
0238:
0239:                    MethodInfo[] methodInfos;
0240:                    {
0241:                        short methodsCount = dis.readShort();
0242:                        methodInfos = new MethodInfo[methodsCount];
0243:                        for (int i = 0; i < methodsCount; ++i)
0244:                            methodInfos[i] = this .readMethodInfo(dis);
0245:                    }
0246:
0247:                    AttributeInfo[] attributes;
0248:                    {
0249:                        short attributesCount = dis.readShort();
0250:                        attributes = new AttributeInfo[attributesCount];
0251:                        for (short i = 0; i < attributesCount; ++i)
0252:                            attributes[i] = this .readAttributeInfo(dis);
0253:                    }
0254:
0255:                    Map sourceLines = new HashMap();
0256:                    READ_SOURCE_LINES: {
0257:                        for (int i = 0; i < attributes.length; ++i) {
0258:                            if (attributes[i] instanceof  SourceFileAttribute) {
0259:                                ConstantPoolInfo cpi = Disassembler.this 
0260:                                        .getConstantPoolEntry(((SourceFileAttribute) attributes[i]).sourceFileIndex);
0261:                                if (cpi instanceof  ConstantUtf8Info) {
0262:                                    String sourceFile = ((ConstantUtf8Info) cpi)
0263:                                            .getValue();
0264:                                    LineNumberReader lnr;
0265:                                    try {
0266:                                        lnr = new LineNumberReader(
0267:                                                new FileReader(new File(
0268:                                                        this .sourceDirectory,
0269:                                                        sourceFile)));
0270:                                    } catch (FileNotFoundException ex) {
0271:                                        ;
0272:                                        break READ_SOURCE_LINES;
0273:                                    }
0274:                                    try {
0275:                                        for (;;) {
0276:                                            String sl = lnr.readLine();
0277:                                            if (sl == null)
0278:                                                break;
0279:                                            sourceLines.put(new Integer(lnr
0280:                                                    .getLineNumber()), sl);
0281:                                        }
0282:                                    } finally {
0283:                                        lnr.close();
0284:                                    }
0285:                                }
0286:                            }
0287:                        }
0288:                    }
0289:
0290:                    this .indentln("methods[] = {");
0291:                    {
0292:                        for (short i = 0; i < methodInfos.length; ++i) {
0293:                            methodInfos[i].print(sourceLines);
0294:                            this .println();
0295:                        }
0296:                    }
0297:                    this .unindentln("}");
0298:
0299:                    this .indentln("attributes[] = {");
0300:                    {
0301:                        for (short i = 0; i < attributes.length; ++i) {
0302:                            attributes[i].print();
0303:                            this .println();
0304:                        }
0305:                    }
0306:                    this .unindentln("}");
0307:                }
0308:                this .unindent("}");
0309:            }
0310:
0311:            private ConstantPoolInfo readConstantPoolInfo(
0312:                    final DataInputStream dis) throws IOException {
0313:                byte tag = dis.readByte();
0314:                switch (tag) {
0315:                case 7: {
0316:                    final short nameIndex = dis.readShort();
0317:                    return new ConstantPoolInfo() {
0318:                        public void print() {
0319:                            Disassembler.this .print("CONSTANT_Class_info { ");
0320:                            Disassembler.this .printConstantPoolEntry(
0321:                                    "name_index", nameIndex);
0322:                            Disassembler.this .print(" }");
0323:                        }
0324:                    };
0325:                }
0326:                case 9: {
0327:                    final short classIndex = dis.readShort();
0328:                    final short nameAndTypeIndex = dis.readShort();
0329:                    return new ConstantPoolInfo() {
0330:                        public void print() {
0331:                            Disassembler.this 
0332:                                    .indentln("CONSTANT_Fieldref_info {");
0333:                            {
0334:                                Disassembler.this .printConstantPoolEntry(
0335:                                        "class_index", classIndex);
0336:                                Disassembler.this .println();
0337:                                Disassembler.this 
0338:                                        .printConstantPoolEntry(
0339:                                                "name_and_type_index",
0340:                                                nameAndTypeIndex);
0341:                                Disassembler.this .println();
0342:                            }
0343:                            Disassembler.this .unindent("}");
0344:                        }
0345:                    };
0346:                }
0347:                case 10: {
0348:                    final short classIndex = dis.readShort();
0349:                    final short nameAndTypeIndex = dis.readShort();
0350:                    return new ConstantPoolInfo() {
0351:                        public void print() {
0352:                            Disassembler.this 
0353:                                    .indentln("CONSTANT_Methodref_info {");
0354:                            {
0355:                                Disassembler.this .printConstantPoolEntry(
0356:                                        "class_index", classIndex);
0357:                                Disassembler.this .println();
0358:                                Disassembler.this 
0359:                                        .printConstantPoolEntry(
0360:                                                "name_and_type_index",
0361:                                                nameAndTypeIndex);
0362:                                Disassembler.this .println();
0363:                            }
0364:                            Disassembler.this .unindent("}");
0365:                        }
0366:                    };
0367:                }
0368:                case 11: {
0369:                    final short classIndex = dis.readShort();
0370:                    final short nameAndTypeIndex = dis.readShort();
0371:                    return new ConstantPoolInfo() {
0372:                        public void print() {
0373:                            Disassembler.this 
0374:                                    .indentln("CONSTANT_InterfaceMethodref_info {");
0375:                            {
0376:                                Disassembler.this .printConstantPoolEntry(
0377:                                        "class_index", classIndex);
0378:                                Disassembler.this .println();
0379:                                Disassembler.this 
0380:                                        .printConstantPoolEntry(
0381:                                                "name_and_type_index",
0382:                                                nameAndTypeIndex);
0383:                                Disassembler.this .println();
0384:                            }
0385:                            Disassembler.this .unindent("}");
0386:                        }
0387:                    };
0388:                }
0389:                case 8: {
0390:                    final short stringIndex = dis.readShort();
0391:                    return new ConstantPoolInfo() {
0392:                        public void print() {
0393:                            ConstantPoolInfo cpi = Disassembler.this 
0394:                                    .getConstantPoolEntry(stringIndex);
0395:                            String s;
0396:                            if (cpi == null) {
0397:                                s = "INVALID CONSTANT POOL INDEX";
0398:                            } else if (!(cpi instanceof  ConstantUtf8Info)) {
0399:                                s = "STRING CONSTANT VALUE IS NOT UTF8";
0400:                            } else {
0401:                                s = ((ConstantUtf8Info) cpi).getValue();
0402:                                if (s.length() > 80) {
0403:                                    s = Disassembler.stringToJavaLiteral(s
0404:                                            .substring(0, 80))
0405:                                            + "... (" + s.length() + " chars)";
0406:                                } else {
0407:                                    s = Disassembler.stringToJavaLiteral(s);
0408:                                }
0409:                            }
0410:                            if (Disassembler.this .verbose) {
0411:                                Disassembler.this 
0412:                                        .print("CONSTANT_String_info { string_index = "
0413:                                                + stringIndex
0414:                                                + " ("
0415:                                                + s
0416:                                                + ") }");
0417:                            } else {
0418:                                Disassembler.this .print(s);
0419:                            }
0420:                        }
0421:                    };
0422:                }
0423:                case 3: {
0424:                    final int bytes = dis.readInt();
0425:                    return new ConstantPoolInfo() {
0426:                        public void print() {
0427:                            Disassembler.this 
0428:                                    .print("CONSTANT_Integer_info { bytes = "
0429:                                            + bytes + " }");
0430:                        }
0431:                    };
0432:                }
0433:                case 4: {
0434:                    final float bytes = dis.readFloat();
0435:                    return new ConstantPoolInfo() {
0436:                        public void print() {
0437:                            Disassembler.this 
0438:                                    .print("CONSTANT_Float_info { bytes = "
0439:                                            + bytes + " }");
0440:                        }
0441:                    };
0442:                }
0443:                case 5: {
0444:                    final long bytes = dis.readLong();
0445:                    return new ConstantPoolInfo() {
0446:                        public void print() {
0447:                            Disassembler.this 
0448:                                    .print("CONSTANT_Long_info { high_bytes/low_bytes = "
0449:                                            + bytes + " }");
0450:                        }
0451:
0452:                        public int getSizeInConstantPool() {
0453:                            return 2;
0454:                        }
0455:                    };
0456:                }
0457:                case 6: {
0458:                    final double bytes = dis.readDouble();
0459:                    return new ConstantPoolInfo() {
0460:                        public void print() {
0461:                            Disassembler.this 
0462:                                    .print("CONSTANT_Double_info { high_bytes/low_bytes = "
0463:                                            + bytes + " }");
0464:                        }
0465:
0466:                        public int getSizeInConstantPool() {
0467:                            return 2;
0468:                        }
0469:                    };
0470:                }
0471:                case 12: {
0472:                    final short nameIndex = dis.readShort();
0473:                    final short descriptorIndex = dis.readShort();
0474:                    return new ConstantPoolInfo() {
0475:                        public void print() {
0476:                            Disassembler.this 
0477:                                    .indentln("CONSTANT_NameAndType_info {");
0478:                            {
0479:                                Disassembler.this .printConstantPoolEntry(
0480:                                        "name_index", nameIndex);
0481:                                Disassembler.this .println();
0482:                                Disassembler.this .printConstantPoolEntry(
0483:                                        "descriptor_index", descriptorIndex);
0484:                                Disassembler.this .println();
0485:                            }
0486:                            Disassembler.this .unindent("}");
0487:                        }
0488:                    };
0489:                }
0490:                case 1:
0491:                    return new ConstantUtf8Info(dis.readUTF());
0492:                default:
0493:                    throw new RuntimeException("Invalid cp_info tag \""
0494:                            + (int) tag + "\"");
0495:                }
0496:            }
0497:
0498:            private static String stringToJavaLiteral(String s) {
0499:                for (int i = 0; i < s.length();) {
0500:                    char c = s.charAt(i);
0501:                    int idx = "\r\n\"\t\b".indexOf(c);
0502:                    if (idx == -1) {
0503:                        ++i;
0504:                    } else {
0505:                        s = s.substring(0, i) + '\\' + "rn\"tb".charAt(idx)
0506:                                + s.substring(i + 1);
0507:                        i += 2;
0508:                    }
0509:                    if (i >= 80)
0510:                        break;
0511:                }
0512:                return '"' + s + '"';
0513:            }
0514:
0515:            private void disasmFieldInfo(DataInputStream dis)
0516:                    throws IOException {
0517:                this .indentln("field_info {");
0518:                {
0519:                    this .println("access_flags = "
0520:                            + decodeAccess(dis.readShort()));
0521:
0522:                    this .printConstantPoolEntry("name_index", dis.readShort());
0523:                    this .println();
0524:
0525:                    this .printConstantPoolEntry("descriptor_index", dis
0526:                            .readShort());
0527:                    this .println();
0528:
0529:                    this .indentln("attributes[] = {");
0530:                    {
0531:                        short attributesCount = dis.readShort();
0532:                        for (short i = 0; i < attributesCount; ++i) {
0533:                            disasmAttributeInfo(dis);
0534:                            this .println();
0535:                        }
0536:                    }
0537:                    this .unindentln("}");
0538:                }
0539:                this .unindent("}");
0540:            }
0541:
0542:            private MethodInfo readMethodInfo(DataInputStream dis)
0543:                    throws IOException {
0544:                final short accessFlags = dis.readShort();
0545:                final short nameIndex = dis.readShort();
0546:                final short descriptorIndex = dis.readShort();
0547:                final AttributeInfo[] attributeInfos;
0548:                {
0549:                    short attributesCount = dis.readShort();
0550:                    attributeInfos = new AttributeInfo[attributesCount];
0551:                    for (short i = 0; i < attributesCount; ++i)
0552:                        attributeInfos[i] = this .readAttributeInfo(dis);
0553:                }
0554:                return new MethodInfo() {
0555:                    public void print(Map sourceLines) {
0556:                        Disassembler.this .indentln("method_info {");
0557:                        {
0558:                            Disassembler.this .println("access_flags = "
0559:                                    + decodeAccess(accessFlags));
0560:
0561:                            Disassembler.this .printConstantPoolEntry(
0562:                                    "name_index", nameIndex);
0563:                            Disassembler.this .println();
0564:
0565:                            Disassembler.this .printConstantPoolEntry(
0566:                                    "descriptor_index", descriptorIndex);
0567:                            Disassembler.this .println();
0568:
0569:                            Disassembler.this .indentln("attributes[] = {");
0570:                            {
0571:                                for (short i = 0; i < attributeInfos.length; ++i) {
0572:                                    AttributeInfo ai = attributeInfos[i];
0573:                                    if (ai instanceof  SourceRelatedAttributeInfo) {
0574:                                        ((SourceRelatedAttributeInfo) ai)
0575:                                                .print(sourceLines);
0576:                                    } else {
0577:                                        ai.print();
0578:                                    }
0579:                                    Disassembler.this .println();
0580:                                }
0581:                            }
0582:                            Disassembler.this .unindentln("}");
0583:                        }
0584:                        Disassembler.this .unindent("}");
0585:                    }
0586:                };
0587:            }
0588:
0589:            private interface MethodInfo {
0590:                public void print(Map sourceLines // Integer lineNumber => String line
0591:                );
0592:            }
0593:
0594:            private void disasmAttributeInfo(DataInputStream dis)
0595:                    throws IOException {
0596:                this .readAttributeInfo(dis).print();
0597:            }
0598:
0599:            private AttributeInfo readAttributeInfo(DataInputStream dis)
0600:                    throws IOException {
0601:
0602:                // Determine attribute name.
0603:                short attributeNameIndex = dis.readShort();
0604:                String attributeName;
0605:                {
0606:                    ConstantPoolInfo cpi = Disassembler.this 
0607:                            .getConstantPoolEntry(attributeNameIndex);
0608:                    if (cpi == null) {
0609:                        attributeName = "INVALID CONSTANT POOL INDEX";
0610:                    } else if (!(cpi instanceof  ConstantUtf8Info)) {
0611:                        attributeName = "ATTRIBUTE NAME IS NOT UTF8";
0612:                    } else {
0613:                        attributeName = ((ConstantUtf8Info) cpi).getValue();
0614:                    }
0615:                }
0616:
0617:                // Read attribute body into byte array and create a DataInputStream.
0618:                int attributeLength = dis.readInt();
0619:                final byte[] ba = new byte[attributeLength];
0620:                if (dis.read(ba) != ba.length)
0621:                    throw new EOFException();
0622:                ByteArrayInputStream bais = new ByteArrayInputStream(ba);
0623:                DataInputStream dis2 = new DataInputStream(bais);
0624:
0625:                // Parse the attribute body.
0626:                AttributeInfo res = this .readAttributeBody(attributeName, dis2);
0627:
0628:                // Check for extraneous bytes.
0629:                int av = bais.available();
0630:                if (av > 0)
0631:                    throw new RuntimeException(av
0632:                            + " extraneous bytes in attribute \""
0633:                            + attributeName + "\"");
0634:
0635:                return res;
0636:            }
0637:
0638:            private AttributeInfo readAttributeBody(final String attributeName,
0639:                    final DataInputStream dis) throws IOException {
0640:                if (attributeName.equals("ConstantValue")) {
0641:                    final short constantValueIndex = dis.readShort();
0642:                    return new AttributeInfo() {
0643:                        public void print() {
0644:                            Disassembler.this .indent("ConstantValue "
0645:                                    + constantValueIndex + " (");
0646:                            {
0647:                                Disassembler.this 
0648:                                        .printConstantPoolEntry(constantValueIndex);
0649:                            }
0650:                            Disassembler.this .unindent(")");
0651:                        }
0652:                    };
0653:                } else if (attributeName.equals("Code")) {
0654:                    final short maxStack = dis.readShort();
0655:                    final short maxLocals = dis.readShort();
0656:                    final byte[] code = readByteArray(dis, dis.readInt());
0657:                    final ExceptionTableEntry[] exceptionTable = readExceptionTable(dis);
0658:                    final AttributeInfo[] attributes = readAttributes(dis);
0659:                    return new SourceRelatedAttributeInfo() {
0660:                        public void print(Map sourceLines) {
0661:                            Disassembler.this .indentln("Code {");
0662:                            {
0663:                                Disassembler.this .println("max_stack = "
0664:                                        + maxStack);
0665:                                Disassembler.this .println("max_locals = "
0666:                                        + maxLocals);
0667:
0668:                                Disassembler.this .indentln("code = { ");
0669:                                {
0670:                                    LocalVariableTableAttribute localVariableTableAttribute = null;
0671:                                    LineNumberTableAttribute lineNumberTableAttribute = null;
0672:                                    for (int i = 0; i < attributes.length; ++i) {
0673:                                        AttributeInfo a = attributes[i];
0674:                                        if (a instanceof  LocalVariableTableAttribute) {
0675:                                            if (localVariableTableAttribute != null)
0676:                                                throw new RuntimeException(
0677:                                                        "Duplicate LocalVariableTable attribute");
0678:                                            localVariableTableAttribute = (LocalVariableTableAttribute) a;
0679:                                        }
0680:                                        if (a instanceof  LineNumberTableAttribute) {
0681:                                            if (lineNumberTableAttribute != null)
0682:                                                throw new RuntimeException(
0683:                                                        "Duplicate LineNumberTable attribute");
0684:                                            lineNumberTableAttribute = (LineNumberTableAttribute) a;
0685:                                        }
0686:                                    }
0687:                                    try {
0688:                                        disasmBytecode(
0689:                                                new ByteArrayInputStream(code),
0690:                                                localVariableTableAttribute,
0691:                                                lineNumberTableAttribute,
0692:                                                sourceLines);
0693:                                    } catch (IOException ignored) {
0694:                                        ;
0695:                                    }
0696:                                }
0697:                                Disassembler.this .unindentln("}");
0698:
0699:                                Disassembler.this 
0700:                                        .indentln("exception_table = {");
0701:                                {
0702:                                    for (int i = 0; i < exceptionTable.length; ++i) {
0703:                                        exceptionTable[i].print();
0704:                                        Disassembler.this .println();
0705:                                    }
0706:                                }
0707:                                Disassembler.this .unindentln("}");
0708:
0709:                                Disassembler.this .indentln("attributes[] = {");
0710:                                {
0711:                                    for (int i = 0; i < attributes.length; ++i) {
0712:                                        attributes[i].print();
0713:                                        Disassembler.this .println();
0714:                                    }
0715:                                }
0716:                                Disassembler.this .unindentln("}");
0717:                            }
0718:                            Disassembler.this .unindent("}");
0719:                        }
0720:                    };
0721:                } else if (attributeName.equals("Exceptions")) {
0722:                    final short[] exceptionIndexTable = readShortArray(dis, dis
0723:                            .readShort());
0724:                    return new AttributeInfo() {
0725:                        public void print() {
0726:                            Disassembler.this .indentln("Exceptions {");
0727:                            {
0728:                                Disassembler.this 
0729:                                        .indentln("exception_index_table = {");
0730:                                {
0731:                                    for (short i = 0; i < exceptionIndexTable.length; ++i) {
0732:                                        short exceptionIndex = exceptionIndexTable[i];
0733:                                        Disassembler.this .print(exceptionIndex
0734:                                                + " (");
0735:                                        Disassembler.this 
0736:                                                .printConstantPoolEntry(exceptionIndex);
0737:                                        Disassembler.this .println("),");
0738:                                    }
0739:                                }
0740:                                Disassembler.this .unindentln("}");
0741:                            }
0742:                            Disassembler.this .unindent("}");
0743:                        }
0744:                    };
0745:                } else if (attributeName.equals("InnerClasses")) {
0746:                    final short[] data = readShortArray(dis, 4 * dis
0747:                            .readShort());
0748:                    return new AttributeInfo() {
0749:                        public void print() {
0750:                            Disassembler.this .indentln("InnerClasses {");
0751:                            {
0752:                                Disassembler.this .indentln("classes = {");
0753:                                {
0754:                                    for (int i = 0; i < data.length; i += 4) {
0755:                                        Disassembler.this .indentln("{");
0756:                                        {
0757:                                            Disassembler.this 
0758:                                                    .printConstantPoolEntry(
0759:                                                            "inner_class_info_index",
0760:                                                            data[i]);
0761:                                            Disassembler.this .println();
0762:
0763:                                            short outerClassInfoIndex = data[i + 1];
0764:                                            if (outerClassInfoIndex == 0) {
0765:                                                Disassembler.this 
0766:                                                        .print("(not a member)");
0767:                                            } else {
0768:                                                Disassembler.this 
0769:                                                        .printConstantPoolEntry(
0770:                                                                "outer_class_info_index",
0771:                                                                outerClassInfoIndex);
0772:                                            }
0773:                                            Disassembler.this .println();
0774:
0775:                                            short innerNameIndex = data[i + 2];
0776:                                            if (innerNameIndex == 0) {
0777:                                                Disassembler.this 
0778:                                                        .print("(anonymous)");
0779:                                            } else {
0780:                                                Disassembler.this 
0781:                                                        .printConstantPoolEntry(
0782:                                                                "inner_name_index",
0783:                                                                innerNameIndex);
0784:                                            }
0785:                                            Disassembler.this .println();
0786:
0787:                                            Disassembler.this 
0788:                                                    .println("inner_class_access_flags = "
0789:                                                            + decodeAccess(data[i + 3]));
0790:                                        }
0791:                                        Disassembler.this 
0792:                                                .unindentln(i == data.length - 1 ? "}"
0793:                                                        : "},");
0794:                                    }
0795:                                }
0796:                                Disassembler.this .unindentln("}");
0797:                            }
0798:                            Disassembler.this .unindent("}");
0799:                        }
0800:                    };
0801:                } else if (attributeName.equals("Synthetic")) {
0802:                    return new AttributeInfo() {
0803:                        public void print() {
0804:                            Disassembler.this .print("Synthetic");
0805:                        }
0806:                    };
0807:                } else if (attributeName.equals("SourceFile")) {
0808:                    return new SourceFileAttribute(dis.readShort());
0809:                } else if (attributeName.equals("LineNumberTable")) {
0810:                    return new LineNumberTableAttribute(readShortArray(dis,
0811:                            2 * dis.readShort()));
0812:                } else if (attributeName.equals("LocalVariableTable")) {
0813:                    return new LocalVariableTableAttribute(readShortArray(dis,
0814:                            5 * dis.readShort()));
0815:                } else if (attributeName.equals("Deprecated")) {
0816:                    return new AttributeInfo() {
0817:                        public void print() {
0818:                            Disassembler.this .print("Deprecated");
0819:                        }
0820:                    };
0821:                } else {
0822:                    final ByteArrayOutputStream baos = new ByteArrayOutputStream();
0823:                    for (;;) {
0824:                        int c = dis.read();
0825:                        if (c == -1)
0826:                            break;
0827:                        baos.write(c);
0828:                    }
0829:                    return new AttributeInfo() {
0830:                        public void print() {
0831:                            Disassembler.this .indentln(attributeName + " {");
0832:                            {
0833:                                Disassembler.this .print("info = { ");
0834:                                for (int i = 0; i < this .info.length; ++i) {
0835:                                    Disassembler.this 
0836:                                            .print("0x"
0837:                                                    + Integer
0838:                                                            .toHexString(0xff & this .info[i])
0839:                                                    + ", ");
0840:                                }
0841:                                Disassembler.this .println("}");
0842:                            }
0843:                            Disassembler.this .unindent("}");
0844:                        }
0845:
0846:                        private byte[] info = baos.toByteArray();
0847:                    };
0848:                }
0849:            }
0850:
0851:            private interface AttributeInfo {
0852:                public void print();
0853:            }
0854:
0855:            private abstract static class SourceRelatedAttributeInfo implements 
0856:                    AttributeInfo {
0857:                public void print() {
0858:                    throw new UnsupportedOperationException("print");
0859:                }
0860:
0861:                public abstract void print(Map sourceLines);
0862:            }
0863:
0864:            private class SourceFileAttribute implements  AttributeInfo {
0865:                final short sourceFileIndex;
0866:
0867:                SourceFileAttribute(short sourceFileIndex) {
0868:                    this .sourceFileIndex = sourceFileIndex;
0869:                }
0870:
0871:                public void print() {
0872:                    Disassembler.this .indentln("SourceFile {");
0873:                    {
0874:                        Disassembler.this .printConstantPoolEntry(
0875:                                "sourcefile_index", this .sourceFileIndex);
0876:                        Disassembler.this .println();
0877:                    }
0878:                    Disassembler.this .unindent("}");
0879:                }
0880:            }
0881:
0882:            public class LineNumberTableAttribute implements  AttributeInfo {
0883:                private final short[] data;
0884:
0885:                public LineNumberTableAttribute(short[] data) {
0886:                    this .data = data;
0887:                }
0888:
0889:                public void print() {
0890:                    Disassembler.this .indentln("LineNumberTable {");
0891:                    {
0892:                        Disassembler.this .indentln("line_number_table = {");
0893:                        {
0894:                            for (short i = 0; i < this .data.length; i += 2) {
0895:                                Disassembler.this .print("start_pc = "
0896:                                        + this .data[i]);
0897:                                Disassembler.this .print(", ");
0898:                                Disassembler.this .println("line_number = "
0899:                                        + this .data[i + 1]);
0900:                            }
0901:                        }
0902:                        Disassembler.this .unindentln("}");
0903:                    }
0904:                    Disassembler.this .unindent("}");
0905:                }
0906:
0907:                public short findLineNumber(short offset) {
0908:                    for (short i = 0; i < this .data.length; i += 2) {
0909:                        if (this .data[i] == offset)
0910:                            return this .data[i + 1];
0911:                    }
0912:                    return -1;
0913:                }
0914:            }
0915:
0916:            private class LocalVariableTableAttribute implements  AttributeInfo {
0917:                public LocalVariableTableAttribute(short[] data) {
0918:                    this .data = data;
0919:                }
0920:
0921:                public void print() {
0922:                    Disassembler.this .indentln("LocalVariableTable {");
0923:                    {
0924:                        Disassembler.this .indentln("local_variable_table = {");
0925:                        {
0926:                            for (int i = 0; i < this .data.length; i += 5) {
0927:                                Disassembler.this .print("start_pc = "
0928:                                        + this .data[i]);
0929:                                Disassembler.this .print(", ");
0930:                                Disassembler.this .print("length = "
0931:                                        + this .data[i + 1]);
0932:                                Disassembler.this .print(", ");
0933:                                Disassembler.this .printConstantPoolEntry(
0934:                                        "name_index", this .data[i + 2]);
0935:                                Disassembler.this .print(", ");
0936:                                Disassembler.this .printConstantPoolEntry(
0937:                                        "descriptor_index", this .data[i + 3]);
0938:                                Disassembler.this .print(", ");
0939:                                Disassembler.this .println("index = "
0940:                                        + this .data[i + 4]);
0941:                            }
0942:                        }
0943:                        Disassembler.this .unindentln("}");
0944:                    }
0945:                    Disassembler.this .unindent("}");
0946:                }
0947:
0948:                public String find(short index, int instructionOffset) {
0949:                    for (int i = 0; i < this .data.length; i += 5) {
0950:                        short startPC = this .data[i];
0951:                        short length = this .data[i + 1];
0952:                        if (instructionOffset >= startPC
0953:                                && instructionOffset <= startPC + length
0954:                                && index == this .data[i + 4]) {
0955:                            String name = ((ConstantUtf8Info) Disassembler.this 
0956:                                    .getConstantPoolEntry(this .data[i + 2]))
0957:                                    .getValue();
0958:                            String descriptor = ((ConstantUtf8Info) Disassembler.this 
0959:                                    .getConstantPoolEntry(this .data[i + 3]))
0960:                                    .getValue();
0961:                            return Disassembler.decodeDescriptor(descriptor)
0962:                                    + " " + name;
0963:                        }
0964:                    }
0965:                    return "anonymous";
0966:                }
0967:
0968:                private short[] data;
0969:            }
0970:
0971:            private static byte[] readByteArray(InputStream is, int size)
0972:                    throws IOException {
0973:                byte[] res = new byte[size];
0974:                if (is.read(res) != size)
0975:                    throw new EOFException("EOF in byte array");
0976:                return res;
0977:            }
0978:
0979:            private ExceptionTableEntry[] readExceptionTable(DataInputStream dis)
0980:                    throws IOException {
0981:                ExceptionTableEntry[] res = new ExceptionTableEntry[dis
0982:                        .readShort()];
0983:                for (short i = 0; i < res.length; ++i) {
0984:                    res[i] = new ExceptionTableEntry(dis.readShort(), dis
0985:                            .readShort(), dis.readShort(), dis.readShort());
0986:                }
0987:                return res;
0988:            }
0989:
0990:            private class ExceptionTableEntry {
0991:                ExceptionTableEntry(short startPC, short endPC,
0992:                        short handlerPC, short catchType) {
0993:                    this .startPC = startPC;
0994:                    this .endPC = endPC;
0995:                    this .handlerPC = handlerPC;
0996:                    this .catchType = catchType;
0997:                }
0998:
0999:                public void print() {
1000:                    Disassembler.this .print("start_pc = " + this .startPC
1001:                            + ", end_pc = " + this .endPC + ", handler_pc = "
1002:                            + this .handlerPC + ", catch_type = "
1003:                            + this .catchType + " (");
1004:                    if (this .catchType == 0) {
1005:                        Disassembler.this .print("finally");
1006:                    } else {
1007:                        Disassembler.this 
1008:                                .printConstantPoolEntry(this .catchType);
1009:                    }
1010:                    Disassembler.this .print(")");
1011:                }
1012:
1013:                private short startPC, endPC, handlerPC, catchType;
1014:            }
1015:
1016:            private AttributeInfo[] readAttributes(DataInputStream dis)
1017:                    throws IOException {
1018:                AttributeInfo[] res = new AttributeInfo[dis.readShort()];
1019:                for (int i = 0; i < res.length; ++i) {
1020:                    res[i] = Disassembler.this .readAttributeInfo(dis);
1021:                }
1022:                return res;
1023:            }
1024:
1025:            private static short[] readShortArray(DataInputStream dis, int size)
1026:                    throws IOException {
1027:                short[] res = new short[size];
1028:                for (int i = 0; i < res.length; ++i)
1029:                    res[i] = dis.readShort();
1030:                return res;
1031:            }
1032:
1033:            private void disasmBytecode(InputStream is,
1034:                    LocalVariableTableAttribute localVariableTableAttribute,
1035:                    LineNumberTableAttribute lineNumberTableAttribute,
1036:                    Map sourceLines // Integer lineNumber => String sourceLine
1037:            ) throws IOException {
1038:                CountingInputStream cis = new CountingInputStream(is);
1039:                DataInputStream dis = new DataInputStream(cis);
1040:
1041:                for (;;) {
1042:                    short instructionOffset = (short) cis.getCount();
1043:
1044:                    int opcode = dis.read();
1045:                    if (opcode == -1)
1046:                        return; // EOF
1047:
1048:                    if (lineNumberTableAttribute != null) {
1049:                        short lineNumber = lineNumberTableAttribute
1050:                                .findLineNumber(instructionOffset);
1051:                        if (lineNumber != -1) {
1052:                            String sourceLine = (String) sourceLines
1053:                                    .get(new Integer(lineNumber));
1054:                            if (sourceLine == null)
1055:                                sourceLine = "(Source line not available)";
1056:                            this .println("            Line " + lineNumber
1057:                                    + ": " + sourceLine);
1058:                        }
1059:                    }
1060:                    this .print(instructionOffset + ": ");
1061:
1062:                    Instruction instruction = opcodeToInstruction[opcode];
1063:                    if (instruction == null) {
1064:                        this .println("??? (invalid opcode \"" + opcode + "\")");
1065:                        continue;
1066:                    }
1067:                    disasmInstruction(instruction, dis, instructionOffset,
1068:                            localVariableTableAttribute);
1069:                    this .println();
1070:                }
1071:            }
1072:
1073:            private void disasmInstruction(Instruction instruction,
1074:                    DataInputStream dis, int instructionOffset,
1075:                    LocalVariableTableAttribute localVariableTableAttribute)
1076:                    throws IOException {
1077:                this .print(instruction.getMnemonic());
1078:                Operand[] operands = instruction.getOperands();
1079:                if (operands != null) {
1080:                    for (int i = 0; i < operands.length; ++i) {
1081:                        Operand operand = operands[i];
1082:                        this .print(" ");
1083:                        operand.disasm(dis, instructionOffset,
1084:                                localVariableTableAttribute, this );
1085:                    }
1086:                }
1087:            }
1088:
1089:            private static final String[] instructions = new String[] {
1090:                    "50  aaload",
1091:                    "83  aastore",
1092:                    "1   aconst_null",
1093:                    "25  aload         localvariablearrayindex1",
1094:                    "42  aload_0       localvariablearrayindex_0",
1095:                    "43  aload_1       localvariablearrayindex_1",
1096:                    "44  aload_2       localvariablearrayindex_2",
1097:                    "45  aload_3       localvariablearrayindex_3",
1098:                    "189 anewarray     constantpoolindex2",
1099:                    "176 areturn",
1100:                    "190 arraylength",
1101:                    "58  astore        localvariablearrayindex1",
1102:                    "75  astore_0      localvariablearrayindex_0",
1103:                    "76  astore_1      localvariablearrayindex_1",
1104:                    "77  astore_2      localvariablearrayindex_2",
1105:                    "78  astore_3      localvariablearrayindex_3",
1106:                    "191 athrow",
1107:                    "51  baload",
1108:                    "84  bastore",
1109:                    "16  bipush        signedbyte",
1110:                    "52  caload",
1111:                    "85  castore",
1112:                    "192 checkcast     constantpoolindex2",
1113:                    "144 d2f",
1114:                    "142 d2i",
1115:                    "143 d2l",
1116:                    "99  dadd",
1117:                    "49  daload",
1118:                    "82  dastore",
1119:                    "152 dcmpg",
1120:                    "151 dcmpl",
1121:                    "14  dconst_0",
1122:                    "15  dconst_1",
1123:                    "111 ddiv",
1124:                    "24  dload         localvariablearrayindex1",
1125:                    "38  dload_0       localvariablearrayindex_0",
1126:                    "39  dload_1       localvariablearrayindex_1",
1127:                    "40  dload_2       localvariablearrayindex_2",
1128:                    "41  dload_3       localvariablearrayindex_3",
1129:                    "107 dmul",
1130:                    "119 dneg",
1131:                    "115 drem",
1132:                    "175 dreturn",
1133:                    "57  dstore        localvariablearrayindex1",
1134:                    "71  dstore_0      localvariablearrayindex_0",
1135:                    "72  dstore_1      localvariablearrayindex_1",
1136:                    "73  dstore_2      localvariablearrayindex_2",
1137:                    "74  dstore_3      localvariablearrayindex_3",
1138:                    "103 dsub",
1139:                    "89  dup",
1140:                    "90  dup_x1",
1141:                    "91  dup_x2",
1142:                    "92  dup2",
1143:                    "93  dup2_x1",
1144:                    "94  dup2_x2",
1145:                    "141 f2d",
1146:                    "139 f2i",
1147:                    "140 f2l",
1148:                    "98  fadd",
1149:                    "48  faload",
1150:                    "81  fastore",
1151:                    "150 fcmpg",
1152:                    "149 fcmpl",
1153:                    "11  fconst_0",
1154:                    "12  fconst_1",
1155:                    "13  fconst_2",
1156:                    "110 fdiv",
1157:                    "23  fload         localvariablearrayindex1",
1158:                    "34  fload_0       localvariablearrayindex_0",
1159:                    "35  fload_1       localvariablearrayindex_1",
1160:                    "36  fload_2       localvariablearrayindex_2",
1161:                    "37  fload_3       localvariablearrayindex_3",
1162:                    "106 fmul",
1163:                    "118 fneg",
1164:                    "114 frem",
1165:                    "174 freturn",
1166:                    "56  fstore        localvariablearrayindex1",
1167:                    "67  fstore_0      localvariablearrayindex_0",
1168:                    "68  fstore_1      localvariablearrayindex_1",
1169:                    "69  fstore_2      localvariablearrayindex_2",
1170:                    "70  fstore_3      localvariablearrayindex_3",
1171:                    "102 fsub",
1172:                    "180 getfield      constantpoolindex2",
1173:                    "178 getstatic     constantpoolindex2",
1174:                    "167 goto          branchoffset2",
1175:                    "200 goto_w        branchoffset4",
1176:                    "145 i2b",
1177:                    "146 i2c",
1178:                    "135 i2d",
1179:                    "134 i2f",
1180:                    "133 i2l",
1181:                    "147 i2s",
1182:                    "96  iadd",
1183:                    "46  iaload",
1184:                    "126 iand",
1185:                    "79  iastore",
1186:                    "2   iconst_m1",
1187:                    "3   iconst_0",
1188:                    "4   iconst_1",
1189:                    "5   iconst_2",
1190:                    "6   iconst_3",
1191:                    "7   iconst_4",
1192:                    "8   iconst_5",
1193:                    "108 idiv",
1194:                    "165 if_acmpeq",
1195:                    "166 if_acmpne",
1196:                    "159 if_icmpeq     branchoffset2",
1197:                    "160 if_icmpne     branchoffset2",
1198:                    "161 if_icmplt     branchoffset2",
1199:                    "162 if_icmpge     branchoffset2",
1200:                    "163 if_icmpgt     branchoffset2",
1201:                    "164 if_icmple     branchoffset2",
1202:                    "153 ifeq          branchoffset2",
1203:                    "154 ifne          branchoffset2",
1204:                    "155 iflt          branchoffset2",
1205:                    "156 ifge          branchoffset2",
1206:                    "157 ifgt          branchoffset2",
1207:                    "158 ifle          branchoffset2",
1208:                    "199 ifnonnull     branchoffset2",
1209:                    "198 ifnull        branchoffset2",
1210:                    "132 iinc          localvariablearrayindex1 signedbyte",
1211:                    "21  iload         localvariablearrayindex1",
1212:                    "26  iload_0       localvariablearrayindex_0",
1213:                    "27  iload_1       localvariablearrayindex_1",
1214:                    "28  iload_2       localvariablearrayindex_2",
1215:                    "29  iload_3       localvariablearrayindex_3",
1216:                    "104 imul",
1217:                    "116 ineg",
1218:                    "193 instanceof      constantpoolindex2",
1219:                    "185 invokeinterface constantpoolindex2 signedbyte signedbyte",
1220:                    "183 invokespecial   constantpoolindex2",
1221:                    "184 invokestatic    constantpoolindex2",
1222:                    "182 invokevirtual   constantpoolindex2", "128 ior",
1223:                    "112 irem", "172 ireturn", "120 ishl", "122 ishr",
1224:                    "54  istore          localvariablearrayindex1",
1225:                    "59  istore_0        localvariablearrayindex_0",
1226:                    "60  istore_1        localvariablearrayindex_1",
1227:                    "61  istore_2        localvariablearrayindex_2",
1228:                    "62  istore_3        localvariablearrayindex_3",
1229:                    "100 isub", "124 iushr", "130 ixor",
1230:                    "168 jsr             branchoffset2",
1231:                    "201 jsr_w           branchoffset4", "138 l2d", "137 l2f",
1232:                    "136 l2i", "97  ladd", "47  laload", "127 land",
1233:                    "80  lastore", "148 lcmp", "9   lconst_0", "10  lconst_1",
1234:                    "18  ldc           constantpoolindex1",
1235:                    "19  ldc_w         constantpoolindex2",
1236:                    "20  ldc2_w        constantpoolindex2", "109 ldiv",
1237:                    "22  lload         localvariablearrayindex1",
1238:                    "30  lload_0       localvariablearrayindex_0",
1239:                    "31  lload_1       localvariablearrayindex_1",
1240:                    "32  lload_2       localvariablearrayindex_2",
1241:                    "33  lload_3       localvariablearrayindex_3", "105 lmul",
1242:                    "117 lneg", "171 lookupswitch  lookupswitch", "129 lor",
1243:                    "113 lrem", "173 lreturn", "121 lshl", "123 lshr",
1244:                    "55  lstore        localvariablearrayindex1",
1245:                    "63  lstore_0      localvariablearrayindex_0",
1246:                    "64  lstore_1      localvariablearrayindex_1",
1247:                    "65  lstore_2      localvariablearrayindex_2",
1248:                    "66  lstore_3      localvariablearrayindex_3", "101 lsub",
1249:                    "125 lushr", "131 lxor", "194 monitorenter",
1250:                    "195 monitorexit",
1251:                    "197 multianewarray constantpoolindex2 unsignedbyte",
1252:                    "187 new           constantpoolindex2",
1253:                    "188 newarray      atype", "0   nop", "87  pop",
1254:                    "88  pop2", "181 putfield      constantpoolindex2",
1255:                    "179 putstatic     constantpoolindex2",
1256:                    "169 ret           localvariablearrayindex1", "177 return",
1257:                    "53  saload", "86  sastore",
1258:                    "17  sipush        signedshort", "95  swap",
1259:                    "170 tableswitch   tableswitch", "196 wide          wide", };
1260:            private static final String[] wideInstructions = new String[] {
1261:                    "21  iload         localvariablearrayindex2",
1262:                    "23  fload         localvariablearrayindex2",
1263:                    "25  aload         localvariablearrayindex2",
1264:                    "22  lload         localvariablearrayindex2",
1265:                    "24  dload         localvariablearrayindex2",
1266:                    "54  istore        localvariablearrayindex2",
1267:                    "56  fstore        localvariablearrayindex2",
1268:                    "58  astore        localvariablearrayindex2",
1269:                    "55  lstore        localvariablearrayindex2",
1270:                    "57  dstore        localvariablearrayindex2",
1271:                    "169 ret           localvariablearrayindex2",
1272:                    "132 iinc          localvariablearrayindex2 signedshort", };
1273:            private static final Instruction[] opcodeToInstruction = new Instruction[256];
1274:            private static final Instruction[] opcodeToWideInstruction = new Instruction[256];
1275:            static {
1276:                compileInstructions(instructions, opcodeToInstruction);
1277:                compileInstructions(wideInstructions, opcodeToWideInstruction);
1278:            }
1279:
1280:            private static void compileInstructions(String[] instructions,
1281:                    Instruction[] opcodeToInstruction) {
1282:                for (int j = 0; j < instructions.length; ++j) {
1283:                    StringTokenizer st = new StringTokenizer(instructions[j]);
1284:                    String os = st.nextToken();
1285:                    int opcode = Integer.parseInt(os);
1286:                    String mnemonic = st.nextToken();
1287:                    Operand[] operands = null;
1288:                    if (st.hasMoreTokens()) {
1289:                        List l = new ArrayList();
1290:                        while (st.hasMoreTokens()) {
1291:                            String s = st.nextToken();
1292:                            Operand operand;
1293:                            if (s.equals("constantpoolindex1")) {
1294:                                operand = new Operand() {
1295:                                    public void disasm(
1296:                                            DataInputStream dis,
1297:                                            int instructionOffset,
1298:                                            LocalVariableTableAttribute localVariableTableAttribute,
1299:                                            Disassembler d) throws IOException {
1300:                                        short index = (short) (0xff & dis
1301:                                                .readByte());
1302:                                        d.printConstantPoolEntry(index);
1303:                                    }
1304:                                };
1305:                            } else if (s.equals("constantpoolindex2")) {
1306:                                operand = new Operand() {
1307:                                    public void disasm(
1308:                                            DataInputStream dis,
1309:                                            int instructionOffset,
1310:                                            LocalVariableTableAttribute localVariableTableAttribute,
1311:                                            Disassembler d) throws IOException {
1312:                                        d.printConstantPoolEntry(dis
1313:                                                .readShort());
1314:                                    }
1315:                                };
1316:                            } else if (s.equals("localvariablearrayindex1")) {
1317:                                operand = new Operand() {
1318:                                    public void disasm(
1319:                                            DataInputStream dis,
1320:                                            int instructionOffset,
1321:                                            LocalVariableTableAttribute localVariableTableAttribute,
1322:                                            Disassembler d) throws IOException {
1323:                                        short index = dis.readByte();
1324:                                        d.print(index);
1325:                                        if (localVariableTableAttribute != null) {
1326:                                            d
1327:                                                    .print(" ("
1328:                                                            + localVariableTableAttribute
1329:                                                                    .find(
1330:                                                                            index,
1331:                                                                            instructionOffset + 2)
1332:                                                            + ")");
1333:                                        }
1334:                                    }
1335:                                };
1336:                            } else if (s.equals("localvariablearrayindex2")) {
1337:                                operand = new Operand() {
1338:                                    public void disasm(
1339:                                            DataInputStream dis,
1340:                                            int instructionOffset,
1341:                                            LocalVariableTableAttribute localVariableTableAttribute,
1342:                                            Disassembler d) throws IOException {
1343:                                        short index = dis.readShort();
1344:                                        d.print(index);
1345:                                        if (localVariableTableAttribute != null) {
1346:                                            d
1347:                                                    .print(" ("
1348:                                                            + localVariableTableAttribute
1349:                                                                    .find(
1350:                                                                            index,
1351:                                                                            instructionOffset + 3)
1352:                                                            + ")");
1353:                                        }
1354:                                    }
1355:                                };
1356:                            } else if (s.startsWith("localvariablearrayindex_")) {
1357:                                final short index = Short.parseShort(s
1358:                                        .substring(s.length() - 1));
1359:                                operand = new Operand() {
1360:                                    public void disasm(
1361:                                            DataInputStream dis,
1362:                                            int instructionOffset,
1363:                                            LocalVariableTableAttribute localVariableTableAttribute,
1364:                                            Disassembler d) throws IOException {
1365:                                        if (localVariableTableAttribute != null) {
1366:                                            d
1367:                                                    .print("("
1368:                                                            + localVariableTableAttribute
1369:                                                                    .find(
1370:                                                                            index,
1371:                                                                            instructionOffset + 1)
1372:                                                            + ")");
1373:                                        }
1374:                                    }
1375:                                };
1376:                            } else if (s.equals("branchoffset2")) {
1377:                                operand = new Operand() {
1378:                                    public void disasm(
1379:                                            DataInputStream dis,
1380:                                            int instructionOffset,
1381:                                            LocalVariableTableAttribute localVariableTableAttribute,
1382:                                            Disassembler d) throws IOException {
1383:                                        d.print(instructionOffset
1384:                                                + dis.readShort());
1385:                                    }
1386:                                };
1387:                            } else if (s.equals("branchoffset4")) {
1388:                                operand = new Operand() {
1389:                                    public void disasm(
1390:                                            DataInputStream dis,
1391:                                            int instructionOffset,
1392:                                            LocalVariableTableAttribute localVariableTableAttribute,
1393:                                            Disassembler d) throws IOException {
1394:                                        d.print(instructionOffset
1395:                                                + dis.readInt());
1396:                                    }
1397:                                };
1398:                            } else if (s.equals("signedbyte")) {
1399:                                operand = new Operand() {
1400:                                    public void disasm(
1401:                                            DataInputStream dis,
1402:                                            int instructionOffset,
1403:                                            LocalVariableTableAttribute localVariableTableAttribute,
1404:                                            Disassembler d) throws IOException {
1405:                                        d.print(dis.readByte());
1406:                                    }
1407:                                };
1408:                            } else if (s.equals("unsignedbyte")) {
1409:                                operand = new Operand() {
1410:                                    public void disasm(
1411:                                            DataInputStream dis,
1412:                                            int instructionOffset,
1413:                                            LocalVariableTableAttribute localVariableTableAttribute,
1414:                                            Disassembler d) throws IOException {
1415:                                        d.print(0xff & dis.readByte());
1416:                                    }
1417:                                };
1418:                            } else if (s.equals("atype")) {
1419:                                operand = new Operand() {
1420:                                    public void disasm(
1421:                                            DataInputStream dis,
1422:                                            int instructionOffset,
1423:                                            LocalVariableTableAttribute localVariableTableAttribute,
1424:                                            Disassembler d) throws IOException {
1425:                                        byte b = dis.readByte();
1426:                                        d
1427:                                                .print(b == 4 ? "BOOLEAN"
1428:                                                        : b == 5 ? "CHAR"
1429:                                                                : b == 6 ? "FLOAT"
1430:                                                                        : b == 7 ? "DOUBLE"
1431:                                                                                : b == 8 ? "BYTE"
1432:                                                                                        : b == 9 ? "SHORT"
1433:                                                                                                : b == 10 ? "INT"
1434:                                                                                                        : b == 11 ? "LONG"
1435:                                                                                                                : new Integer(
1436:                                                                                                                        0xff & b)
1437:                                                                                                                        .toString());
1438:                                    }
1439:                                };
1440:                            } else if (s.equals("signedshort")) {
1441:                                operand = new Operand() {
1442:                                    public void disasm(
1443:                                            DataInputStream dis,
1444:                                            int instructionOffset,
1445:                                            LocalVariableTableAttribute localVariableTableAttribute,
1446:                                            Disassembler d) throws IOException {
1447:                                        d.print(dis.readShort());
1448:                                    }
1449:                                };
1450:                            } else if (s.equals("tableswitch")) {
1451:                                operand = new Operand() {
1452:                                    public void disasm(
1453:                                            DataInputStream dis,
1454:                                            int instructionOffset,
1455:                                            LocalVariableTableAttribute localVariableTableAttribute,
1456:                                            Disassembler d) throws IOException {
1457:                                        int npads = 3 - (instructionOffset % 4);
1458:                                        for (int i = 0; i < npads; ++i)
1459:                                            if (dis.readByte() != (byte) 0)
1460:                                                throw new RuntimeException(
1461:                                                        "Non-zero pad byte in \"tableswitch\"");
1462:                                        d.print("default => "
1463:                                                + (instructionOffset + dis
1464:                                                        .readInt()));
1465:                                        int low = dis.readInt();
1466:                                        int high = dis.readInt();
1467:                                        for (int i = low; i <= high; ++i) {
1468:                                            int offset = dis.readInt();
1469:                                            d
1470:                                                    .print(", "
1471:                                                            + i
1472:                                                            + " => "
1473:                                                            + (instructionOffset + offset));
1474:                                        }
1475:                                    }
1476:                                };
1477:                            } else if (s.equals("lookupswitch")) {
1478:                                operand = new Operand() {
1479:                                    public void disasm(
1480:                                            DataInputStream dis,
1481:                                            int instructionOffset,
1482:                                            LocalVariableTableAttribute localVariableTableAttribute,
1483:                                            Disassembler d) throws IOException {
1484:                                        int npads = 3 - (instructionOffset % 4);
1485:                                        for (int i = 0; i < npads; ++i) {
1486:                                            byte b = dis.readByte();
1487:                                            if (b != (byte) 0)
1488:                                                d.print("Padding byte #" + i
1489:                                                        + " is " + (b & 0xff));
1490:                                        }
1491:                                        d.print("default => "
1492:                                                + (instructionOffset + dis
1493:                                                        .readInt()));
1494:                                        int npairs = dis.readInt();
1495:                                        for (int i = 0; i < npairs; ++i) {
1496:                                            int match = dis.readInt();
1497:                                            int offset = dis.readInt();
1498:                                            d
1499:                                                    .print(", "
1500:                                                            + match
1501:                                                            + " => "
1502:                                                            + (instructionOffset + offset));
1503:                                        }
1504:                                    }
1505:                                };
1506:                            } else if (s.equals("wide")) {
1507:                                operand = new Operand() {
1508:                                    public void disasm(
1509:                                            DataInputStream dis,
1510:                                            int instructionOffset,
1511:                                            LocalVariableTableAttribute localVariableTableAttribute,
1512:                                            Disassembler d) throws IOException {
1513:                                        int subopcode = 0xff & dis.readByte();
1514:                                        Instruction wideInstruction = opcodeToWideInstruction[subopcode];
1515:                                        if (wideInstruction == null)
1516:                                            throw new RuntimeException(
1517:                                                    "Invalid opcode "
1518:                                                            + subopcode
1519:                                                            + " after opcode WIDE");
1520:                                        d.disasmInstruction(wideInstruction,
1521:                                                dis, instructionOffset,
1522:                                                localVariableTableAttribute);
1523:                                    }
1524:                                };
1525:                            } else {
1526:                                throw new RuntimeException("Unknown operand \""
1527:                                        + s + "\"");
1528:                            }
1529:                            l.add(operand);
1530:                        }
1531:                        operands = (Operand[]) l.toArray(new Operand[l.size()]);
1532:                    }
1533:                    opcodeToInstruction[opcode] = new Instruction(mnemonic,
1534:                            operands);
1535:                }
1536:            }
1537:
1538:            private ConstantPoolInfo getConstantPoolEntry(short index) {
1539:                if ((index & 0xffff) < this .constantPool.length) {
1540:                    return this .constantPool[index & 0xffff];
1541:                } else {
1542:                    return null;
1543:                }
1544:            }
1545:
1546:            private void printConstantPoolEntry(short index) {
1547:                if (this .verbose)
1548:                    this .print(index + " (");
1549:                if ((index & 0xffff) < this .constantPool.length) {
1550:                    ConstantPoolInfo cpi = this .constantPool[index];
1551:                    if (cpi == null) {
1552:                        this .print("NULL CONSTANT POOL ENTRY");
1553:                    } else {
1554:                        cpi.print();
1555:                    }
1556:                } else {
1557:                    this .print("CONSTANT POOL INDEX OUT OF RANGE");
1558:                }
1559:                if (this .verbose)
1560:                    this .print(")");
1561:            }
1562:
1563:            private void printConstantPoolEntry(String label, short index) {
1564:                if (this .verbose) {
1565:                    if (label != null)
1566:                        this .print(label + " = ");
1567:                    this .print(index + " (");
1568:                    this .printConstantPoolEntry(index);
1569:                    this .print(")");
1570:                } else {
1571:                    if (label != null) {
1572:                        if (label.endsWith("_index"))
1573:                            label = label.substring(0, label.length() - 6);
1574:                        this .print(label + " = ");
1575:                    }
1576:                    this .printConstantPoolEntry(index);
1577:                }
1578:            }
1579:
1580:            private static class Instruction {
1581:
1582:                /**
1583:                 * 
1584:                 * @param mnemonic
1585:                 * @param operands <code>null</code> is equivalent to "zero operands"
1586:                 */
1587:                public Instruction(String mnemonic, Operand[] operands) {
1588:                    this .mnemonic = mnemonic;
1589:                    this .operands = operands;
1590:                }
1591:
1592:                public String getMnemonic() {
1593:                    return this .mnemonic;
1594:                }
1595:
1596:                public Operand[] getOperands() {
1597:                    return this .operands;
1598:                }
1599:
1600:                private final String mnemonic;
1601:                private final Operand[] operands;
1602:            }
1603:
1604:            private interface Operand {
1605:                void disasm(
1606:                        DataInputStream dis,
1607:                        int instructionOffset,
1608:                        LocalVariableTableAttribute localVariableTableAttribute,
1609:                        Disassembler d) throws IOException;
1610:            }
1611:
1612:            /**
1613:             * A variant of {@link PrintWriter} that allows for convenient indentation
1614:             * of output lines.
1615:             */
1616:            private static class IndentPrintWriter extends PrintWriter {
1617:                public IndentPrintWriter(OutputStream os) {
1618:                    super (os);
1619:                }
1620:
1621:                public void write(char[] cbuf, int off, int len) {
1622:                    this .handleIndentation();
1623:                    super .write(cbuf, off, len);
1624:                }
1625:
1626:                public void write(String str, int off, int len) {
1627:                    this .handleIndentation();
1628:                    super .write(str, off, len);
1629:                }
1630:
1631:                public void println() {
1632:                    super .println();
1633:                    this .atBOL = true;
1634:                }
1635:
1636:                public void indent() {
1637:                    ++this .indentation;
1638:                }
1639:
1640:                public void unindent() {
1641:                    --this .indentation;
1642:                }
1643:
1644:                private void handleIndentation() {
1645:                    if (this .atBOL) {
1646:                        for (int i = 0; i < this .indentation; ++i) {
1647:                            super .write(INDENTATION_CHARS, 0,
1648:                                    INDENTATION_CHARS.length);
1649:                        }
1650:                        this .atBOL = false;
1651:                    }
1652:                }
1653:
1654:                private final static char[] INDENTATION_CHARS = new char[] {
1655:                        ' ', ' ' };
1656:
1657:                private boolean atBOL = true;
1658:                private int indentation = 0;
1659:            }
1660:
1661:            private abstract static class ConstantPoolInfo {
1662:                public abstract void print();
1663:
1664:                public int getSizeInConstantPool() {
1665:                    return 1;
1666:                }
1667:            }
1668:
1669:            private class ConstantUtf8Info extends ConstantPoolInfo {
1670:                public ConstantUtf8Info(String value) {
1671:                    this .value = value;
1672:                }
1673:
1674:                public void print() {
1675:                    Disassembler.this .print(this .value);
1676:                }
1677:
1678:                public String getValue() {
1679:                    return this .value;
1680:                }
1681:
1682:                private String value;
1683:            }
1684:
1685:            private ConstantPoolInfo[] constantPool = null;
1686:
1687:            private static class CountingInputStream extends InputStream {
1688:                public CountingInputStream(InputStream is) {
1689:                    this .is = is;
1690:                }
1691:
1692:                public int read() throws IOException {
1693:                    int res = this .is.read();
1694:                    if (res != -1)
1695:                        ++this .count;
1696:                    return res;
1697:                }
1698:
1699:                public int read(byte[] b, int off, int len) throws IOException {
1700:                    int res = super .read(b, off, len);
1701:                    if (res != -1)
1702:                        this .count += res;
1703:                    return res;
1704:                }
1705:
1706:                public long getCount() {
1707:                    return this .count;
1708:                }
1709:
1710:                private InputStream is;
1711:                private long count = 0L;
1712:            }
1713:
1714:            private static String decodeAccess(short n) {
1715:                StringBuffer sb = new StringBuffer();
1716:                if ((n & 0x0007) == 0) {
1717:                    sb.append("package ");
1718:                }
1719:                if ((n & 0x0007) == 1) {
1720:                    sb.append("public ");
1721:                    n &= ~0x0007;
1722:                }
1723:                if ((n & 0x0007) == 2) {
1724:                    sb.append("private ");
1725:                    n &= ~0x0007;
1726:                }
1727:                if ((n & 0x0007) == 4) {
1728:                    sb.append("protected ");
1729:                    n &= ~0x0007;
1730:                }
1731:                if ((n & 0x0008) != 0) {
1732:                    sb.append("static ");
1733:                    n &= ~0x0008;
1734:                }
1735:                if ((n & 0x0010) != 0) {
1736:                    sb.append("final ");
1737:                    n &= ~0x0010;
1738:                }
1739:                if ((n & 0x0020) != 0) {
1740:                    sb.append("super/synchronized ");
1741:                    n &= ~0x0020;
1742:                }
1743:                if ((n & 0x0040) != 0) {
1744:                    sb.append("volatile ");
1745:                    n &= ~0x0040;
1746:                }
1747:                if ((n & 0x0080) != 0) {
1748:                    sb.append("transient ");
1749:                    n &= ~0x0080;
1750:                }
1751:                if ((n & 0x0100) != 0) {
1752:                    sb.append("native ");
1753:                    n &= ~0x0100;
1754:                }
1755:                if ((n & 0x0200) != 0) {
1756:                    sb.append("interface ");
1757:                    n &= ~0x0200;
1758:                }
1759:                if ((n & 0x0400) != 0) {
1760:                    sb.append("abstract ");
1761:                    n &= ~0x0400;
1762:                }
1763:                if ((n & 0x0800) != 0) {
1764:                    sb.append("strict ");
1765:                    n &= ~0x0800;
1766:                }
1767:                if (n != 0)
1768:                    sb.append("+ " + n + " ");
1769:                return sb.substring(0, sb.length() - 1);
1770:            }
1771:
1772:            private static String decodeDescriptor(String d) {
1773:                int brackets = 0;
1774:                while (d.charAt(0) == '[') {
1775:                    ++brackets;
1776:                    d = d.substring(1);
1777:                }
1778:                if (d.length() == 1) {
1779:                    int idx = "BCDFIJSZ".indexOf(d.charAt(0));
1780:                    if (idx != -1)
1781:                        d = PRIMITIVES[idx];
1782:                } else if (d.charAt(0) == 'L'
1783:                        && d.charAt(d.length() - 1) == ';') {
1784:                    d = d.substring(1, d.length() - 1);
1785:                }
1786:                for (; brackets > 0; --brackets)
1787:                    d += "[]";
1788:                return d;
1789:            }
1790:
1791:            private static final String[] PRIMITIVES = { "byte", "char",
1792:                    "double", "float", "int", "long", "short", "boolean" };
1793:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.