Source Code Cross Referenced for CodeAttributeComposer.java in  » Development » proguard » proguard » classfile » editor » 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 » Development » proguard » proguard.classfile.editor 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         * ProGuard -- shrinking, optimization, obfuscation, and preverification
003:         *             of Java bytecode.
004:         *
005:         * Copyright (c) 2002-2007 Eric Lafortune (eric@graphics.cornell.edu)
006:         *
007:         * This library is free software; you can redistribute it and/or modify it
008:         * under the terms of the GNU General Public License as published by the Free
009:         * Software Foundation; either version 2 of the License, or (at your option)
010:         * any later version.
011:         *
012:         * This library is distributed in the hope that it will be useful, but WITHOUT
013:         * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
014:         * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
015:         * for more details.
016:         *
017:         * You should have received a copy of the GNU Lesser General Public License
018:         * along with this library; if not, write to the Free Software Foundation,
019:         * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
020:         */
021:        package proguard.classfile.editor;
022:
023:        import proguard.classfile.*;
024:        import proguard.classfile.attribute.*;
025:        import proguard.classfile.attribute.preverification.*;
026:        import proguard.classfile.attribute.preverification.visitor.*;
027:        import proguard.classfile.attribute.visitor.*;
028:        import proguard.classfile.instruction.*;
029:        import proguard.classfile.instruction.visitor.InstructionVisitor;
030:        import proguard.classfile.util.SimplifiedVisitor;
031:
032:        /**
033:         * This AttributeVisitor accumulates instructions and exceptions, and then
034:         * copies them into code attributes that it visits.
035:         *
036:         * @author Eric Lafortune
037:         */
038:        public class CodeAttributeComposer extends SimplifiedVisitor implements 
039:                AttributeVisitor, InstructionVisitor, ExceptionInfoVisitor,
040:                StackMapFrameVisitor, VerificationTypeVisitor,
041:                LineNumberInfoVisitor, LocalVariableInfoVisitor,
042:                LocalVariableTypeInfoVisitor {
043:            //*
044:            private static final boolean DEBUG = false;
045:            /*/
046:            public  static       boolean DEBUG = true;
047:            //*/
048:
049:            private static final int MAXIMUM_LEVELS = 32;
050:            private static final int INVALID = -1;
051:
052:            private boolean allowExternalExceptionHandlers;
053:
054:            private int maximumCodeLength;
055:            private int codeLength;
056:            private int exceptionTableLength;
057:            private int level = -1;
058:
059:            private byte[] code = new byte[ClassConstants.TYPICAL_CODE_LENGTH];
060:            private int[] oldInstructionOffsets = new int[ClassConstants.TYPICAL_CODE_LENGTH];
061:
062:            private final int[] codeFragmentOffsets = new int[MAXIMUM_LEVELS];
063:            private final int[] codeFragmentLengths = new int[MAXIMUM_LEVELS];
064:            private final int[][] instructionOffsetMap = new int[MAXIMUM_LEVELS][ClassConstants.TYPICAL_CODE_LENGTH];
065:
066:            private ExceptionInfo[] exceptionTable = new ExceptionInfo[ClassConstants.TYPICAL_EXCEPTION_TABLE_LENGTH];
067:
068:            private int expectedStackMapFrameOffset;
069:
070:            private final StackSizeUpdater stackSizeUpdater = new StackSizeUpdater();
071:            private final VariableSizeUpdater variableSizeUpdater = new VariableSizeUpdater();
072:
073:            /**
074:             * Creates a new CodeAttributeComposer that doesn't allow external exception
075:             * handlers.
076:             */
077:            public CodeAttributeComposer() {
078:                this (false);
079:            }
080:
081:            /**
082:             * Creates a new CodeAttributeComposer that optionally allows external
083:             * exception handlers.
084:             */
085:            public CodeAttributeComposer(boolean allowExternalExceptionHandlers) {
086:                this .allowExternalExceptionHandlers = allowExternalExceptionHandlers;
087:            }
088:
089:            /**
090:             * Starts a new code definition.
091:             */
092:            public void reset() {
093:                maximumCodeLength = 0;
094:                codeLength = 0;
095:                exceptionTableLength = 0;
096:                level = -1;
097:            }
098:
099:            /**
100:             * Starts a new code fragment. Branch instructions that are added are
101:             * assumed to be relative within such code fragments.
102:             * @param maximumCodeFragmentLength the maximum length of the code that will
103:             *                                  be added as part of this fragment.
104:             */
105:            public void beginCodeFragment(int maximumCodeFragmentLength) {
106:                level++;
107:
108:                if (level >= MAXIMUM_LEVELS) {
109:                    throw new IllegalArgumentException(
110:                            "Maximum number of code fragment levels exceeded ["
111:                                    + level + "]");
112:                }
113:
114:                // Make sure there is sufficient space for adding the code fragment.
115:                maximumCodeLength += maximumCodeFragmentLength;
116:                if (code.length < maximumCodeLength) {
117:                    byte[] newCode = new byte[maximumCodeLength];
118:                    System.arraycopy(code, 0, newCode, 0, codeLength);
119:                    code = newCode;
120:
121:                    int[] newOldInstructionOffsets = new int[maximumCodeLength];
122:                    System.arraycopy(oldInstructionOffsets, 0,
123:                            newOldInstructionOffsets, 0, codeLength);
124:                    oldInstructionOffsets = newOldInstructionOffsets;
125:                }
126:
127:                // Try to reuse the previous array for this code fragment.
128:                if (instructionOffsetMap[level].length <= maximumCodeFragmentLength) {
129:                    instructionOffsetMap[level] = new int[maximumCodeFragmentLength + 1];
130:                }
131:
132:                // Initialize the offset map.
133:                for (int index = 0; index <= maximumCodeFragmentLength; index++) {
134:                    instructionOffsetMap[level][index] = INVALID;
135:                }
136:
137:                // Remember the location of the code fragment.
138:                codeFragmentOffsets[level] = codeLength;
139:                codeFragmentLengths[level] = maximumCodeFragmentLength;
140:            }
141:
142:            /**
143:             * Appends the given instruction with the given old offset.
144:             * @param oldInstructionOffset the old offset of the instruction, to which
145:             *                             branches and other references in the current
146:             *                             code fragment are pointing.
147:             * @param instruction          the instruction to be appended.
148:             */
149:            public void appendInstruction(int oldInstructionOffset,
150:                    Instruction instruction) {
151:                if (DEBUG) {
152:                    println("[" + codeLength + "] <- ", instruction
153:                            .toString(oldInstructionOffset));
154:                }
155:
156:                // Remember the old offset of the appended instruction.
157:                oldInstructionOffsets[codeLength] = oldInstructionOffset;
158:
159:                // Write the instruction.
160:                instruction.write(code, codeLength);
161:
162:                // Fill out the new offset of the appended instruction.
163:                instructionOffsetMap[level][oldInstructionOffset] = codeLength;
164:
165:                // Continue appending at the next instruction offset.
166:                codeLength += instruction.length(codeLength);
167:            }
168:
169:            /**
170:             * Appends the given label with the given old offset.
171:             * @param oldInstructionOffset the old offset of the label, to which
172:             *                             branches and other references in the current
173:             *                             code fragment are pointing.
174:             */
175:            public void appendLabel(int oldInstructionOffset) {
176:                if (DEBUG) {
177:                    println("[" + codeLength + "] <- ", "["
178:                            + oldInstructionOffset + "] (label)");
179:                }
180:
181:                // Fill out the new offset of the appended instruction.
182:                instructionOffsetMap[level][oldInstructionOffset] = codeLength;
183:            }
184:
185:            /**
186:             * Appends the given exception to the exception table.
187:             * @param exceptionInfo the exception to be appended.
188:             */
189:            public void appendException(ExceptionInfo exceptionInfo) {
190:                if (DEBUG) {
191:                    print("         ", "Exception [" + exceptionInfo.u2startPC
192:                            + " -> " + exceptionInfo.u2endPC + ": "
193:                            + exceptionInfo.u2handlerPC + "]");
194:                }
195:
196:                // Remap the exception right away.
197:                visitExceptionInfo(null, null, null, exceptionInfo);
198:
199:                if (DEBUG) {
200:                    System.out.println(" -> [" + exceptionInfo.u2startPC
201:                            + " -> " + exceptionInfo.u2endPC + ": "
202:                            + exceptionInfo.u2handlerPC + "]");
203:                }
204:
205:                // Don't add the exception if its instruction range is empty.
206:                if (exceptionInfo.u2startPC == exceptionInfo.u2endPC) {
207:                    if (DEBUG) {
208:                        println("         ",
209:                                "  (not added because of empty instruction range)");
210:                    }
211:
212:                    return;
213:                }
214:
215:                // Make sure there is sufficient space in the exception table.
216:                if (exceptionTable.length <= exceptionTableLength) {
217:                    ExceptionInfo[] newExceptionTable = new ExceptionInfo[exceptionTableLength + 1];
218:                    System.arraycopy(exceptionTable, 0, newExceptionTable, 0,
219:                            exceptionTableLength);
220:                    exceptionTable = newExceptionTable;
221:                }
222:
223:                // Add the exception.
224:                exceptionTable[exceptionTableLength++] = exceptionInfo;
225:            }
226:
227:            /**
228:             * Wraps up the current code fragment, continuing with the previous one on
229:             * the stack.
230:             */
231:            public void endCodeFragment() {
232:                if (level < 0) {
233:                    throw new IllegalArgumentException(
234:                            "Code fragment not begun [" + level + "]");
235:                }
236:
237:                // Remap the instructions of the code fragment.
238:                int instructionOffset = codeFragmentOffsets[level];
239:                while (instructionOffset < codeLength) {
240:                    // Get the next instruction.
241:                    Instruction instruction = InstructionFactory.create(code,
242:                            instructionOffset);
243:
244:                    // Does this instruction still have to be remapped?
245:                    if (oldInstructionOffsets[instructionOffset] >= 0) {
246:                        // Adapt the instruction for its new offset.
247:                        instruction.accept(null, null, null, instructionOffset,
248:                                this );
249:
250:                        // Write the instruction back.
251:                        instruction.write(code, instructionOffset);
252:
253:                        // Don't remap this instruction again.
254:                        oldInstructionOffsets[instructionOffset] = -1;
255:                    }
256:
257:                    // Continue remapping at the next instruction offset.
258:                    instructionOffset += instruction.length(instructionOffset);
259:                }
260:
261:                // Correct the estimated maximum code length, now that we know the
262:                // actual length of this code fragment.
263:                maximumCodeLength += codeLength - codeFragmentOffsets[level]
264:                        - codeFragmentLengths[level];
265:
266:                // Try to remap the exception handlers that couldn't be remapped before.
267:                if (allowExternalExceptionHandlers) {
268:                    for (int index = 0; index < exceptionTableLength; index++) {
269:                        ExceptionInfo exceptionInfo = exceptionTable[index];
270:
271:                        // Unmapped exception handlers are still negated.
272:                        int handlerPC = -exceptionInfo.u2handlerPC;
273:                        if (handlerPC > 0) {
274:                            if (instructionOffsetMap[level][handlerPC] < codeLength) {
275:                                exceptionInfo.u2handlerPC = remapInstructionOffset(handlerPC);
276:                            } else if (level == 0) {
277:                                throw new IllegalStateException(
278:                                        "Couldn't remap exception handler offset ["
279:                                                + handlerPC + "]");
280:                            }
281:                        }
282:                    }
283:                }
284:
285:                level--;
286:            }
287:
288:            // Implementations for AttributeVisitor.
289:
290:            public void visitAnyAttribute(Clazz clazz, Attribute attribute) {
291:            }
292:
293:            public void visitCodeAttribute(Clazz clazz, Method method,
294:                    CodeAttribute codeAttribute) {
295:                if (DEBUG) {
296:                    System.out
297:                            .println("CodeAttributeComposer: putting results in ["
298:                                    + clazz.getName()
299:                                    + "."
300:                                    + method.getName(clazz)
301:                                    + method.getDescriptor(clazz) + "]");
302:                }
303:
304:                if (level != -1) {
305:                    throw new IllegalArgumentException(
306:                            "Code fragment not ended [" + level + "]");
307:                }
308:
309:                level++;
310:
311:                // Make sure the code attribute has sufficient space for the composed
312:                // code.
313:                if (codeAttribute.u4codeLength < codeLength) {
314:                    codeAttribute.code = new byte[codeLength];
315:                }
316:
317:                // Copy the composed code over into the code attribute.
318:                codeAttribute.u4codeLength = codeLength;
319:                System.arraycopy(code, 0, codeAttribute.code, 0, codeLength);
320:
321:                // Remove exceptions with empty code blocks (done before).
322:                //exceptionTableLength =
323:                //    removeEmptyExceptions(exceptionTable, exceptionTableLength);
324:
325:                // Make sure the exception table has sufficient space for the composed
326:                // exceptions.
327:                if (codeAttribute.exceptionTable.length < exceptionTableLength) {
328:                    codeAttribute.exceptionTable = new ExceptionInfo[exceptionTableLength];
329:                }
330:
331:                // Copy the exception table.
332:                codeAttribute.u2exceptionTableLength = exceptionTableLength;
333:                System.arraycopy(exceptionTable, 0,
334:                        codeAttribute.exceptionTable, 0, exceptionTableLength);
335:
336:                // Update the maximum stack size and local variable frame size.
337:                stackSizeUpdater.visitCodeAttribute(clazz, method,
338:                        codeAttribute);
339:                variableSizeUpdater.visitCodeAttribute(clazz, method,
340:                        codeAttribute);
341:
342:                // Remap  the line number table and the local variable table.
343:                codeAttribute.attributesAccept(clazz, method, this );
344:
345:                // Remap the exception table.
346:                //codeAttribute.exceptionsAccept(clazz, method, this);
347:
348:                // Remove exceptions with empty code blocks (done before).
349:                //codeAttribute.u2exceptionTableLength =
350:                //    removeEmptyExceptions(codeAttribute.exceptionTable,
351:                //                          codeAttribute.u2exceptionTableLength);
352:
353:                level--;
354:            }
355:
356:            public void visitStackMapAttribute(Clazz clazz, Method method,
357:                    CodeAttribute codeAttribute,
358:                    StackMapAttribute stackMapAttribute) {
359:                // Remap all stack map entries.
360:                expectedStackMapFrameOffset = -1;
361:                stackMapAttribute.stackMapFramesAccept(clazz, method,
362:                        codeAttribute, this );
363:            }
364:
365:            public void visitStackMapTableAttribute(Clazz clazz, Method method,
366:                    CodeAttribute codeAttribute,
367:                    StackMapTableAttribute stackMapTableAttribute) {
368:                // Remap all stack map table entries.
369:                expectedStackMapFrameOffset = 0;
370:                stackMapTableAttribute.stackMapFramesAccept(clazz, method,
371:                        codeAttribute, this );
372:            }
373:
374:            public void visitLineNumberTableAttribute(Clazz clazz,
375:                    Method method, CodeAttribute codeAttribute,
376:                    LineNumberTableAttribute lineNumberTableAttribute) {
377:                // Remap all line number table entries.
378:                lineNumberTableAttribute.lineNumbersAccept(clazz, method,
379:                        codeAttribute, this );
380:
381:                // Remove line numbers with empty code blocks.
382:                lineNumberTableAttribute.u2lineNumberTableLength = removeEmptyLineNumbers(
383:                        lineNumberTableAttribute.lineNumberTable,
384:                        lineNumberTableAttribute.u2lineNumberTableLength,
385:                        codeAttribute.u4codeLength);
386:            }
387:
388:            public void visitLocalVariableTableAttribute(Clazz clazz,
389:                    Method method, CodeAttribute codeAttribute,
390:                    LocalVariableTableAttribute localVariableTableAttribute) {
391:                // Remap all local variable table entries.
392:                localVariableTableAttribute.localVariablesAccept(clazz, method,
393:                        codeAttribute, this );
394:
395:                // Remove local variables with empty code blocks.
396:                localVariableTableAttribute.u2localVariableTableLength = removeEmptyLocalVariables(
397:                        localVariableTableAttribute.localVariableTable,
398:                        localVariableTableAttribute.u2localVariableTableLength,
399:                        codeAttribute.u2maxLocals);
400:            }
401:
402:            public void visitLocalVariableTypeTableAttribute(
403:                    Clazz clazz,
404:                    Method method,
405:                    CodeAttribute codeAttribute,
406:                    LocalVariableTypeTableAttribute localVariableTypeTableAttribute) {
407:                // Remap all local variable table entries.
408:                localVariableTypeTableAttribute.localVariablesAccept(clazz,
409:                        method, codeAttribute, this );
410:
411:                // Remove local variables with empty code blocks.
412:                localVariableTypeTableAttribute.u2localVariableTypeTableLength = removeEmptyLocalVariableTypes(
413:                        localVariableTypeTableAttribute.localVariableTypeTable,
414:                        localVariableTypeTableAttribute.u2localVariableTypeTableLength,
415:                        codeAttribute.u2maxLocals);
416:            }
417:
418:            // Implementations for InstructionVisitor.
419:
420:            public void visitAnyInstruction(Clazz clazz, Method method,
421:                    CodeAttribute codeAttribute, int offset,
422:                    Instruction instruction) {
423:            }
424:
425:            public void visitBranchInstruction(Clazz clazz, Method method,
426:                    CodeAttribute codeAttribute, int offset,
427:                    BranchInstruction branchInstruction) {
428:                // Adjust the branch offset.
429:                branchInstruction.branchOffset = remapBranchOffset(offset,
430:                        branchInstruction.branchOffset);
431:            }
432:
433:            public void visitAnySwitchInstruction(Clazz clazz, Method method,
434:                    CodeAttribute codeAttribute, int offset,
435:                    SwitchInstruction switchInstruction) {
436:                // Adjust the default jump offset.
437:                switchInstruction.defaultOffset = remapBranchOffset(offset,
438:                        switchInstruction.defaultOffset);
439:
440:                // Adjust the jump offsets.
441:                remapJumpOffsets(offset, switchInstruction.jumpOffsets);
442:            }
443:
444:            // Implementations for ExceptionInfoVisitor.
445:
446:            public void visitExceptionInfo(Clazz clazz, Method method,
447:                    CodeAttribute codeAttribute, ExceptionInfo exceptionInfo) {
448:                // Remap the code offsets. Note that the instruction offset map also has
449:                // an entry for the first offset after the code, for u2endPC.
450:                exceptionInfo.u2startPC = remapInstructionOffset(exceptionInfo.u2startPC);
451:                exceptionInfo.u2endPC = remapInstructionOffset(exceptionInfo.u2endPC);
452:
453:                // See if we can remap the handler right away. Unmapped exception
454:                // handlers are negated, in order to mark them as external.
455:                int handlerPC = exceptionInfo.u2handlerPC;
456:                exceptionInfo.u2handlerPC = allowExternalExceptionHandlers
457:                        && instructionOffsetMap[level][handlerPC] >= codeLength ? -handlerPC
458:                        : remapInstructionOffset(handlerPC);
459:            }
460:
461:            // Implementations for StackMapFrameVisitor.
462:
463:            public void visitAnyStackMapFrame(Clazz clazz, Method method,
464:                    CodeAttribute codeAttribute, int offset,
465:                    StackMapFrame stackMapFrame) {
466:                // Remap the stack map frame offset.
467:                int stackMapFrameOffset = remapInstructionOffset(offset);
468:
469:                int offsetDelta = stackMapFrameOffset;
470:
471:                // Compute the offset delta if the frame is part of a stack map frame
472:                // table (for JDK 6.0) instead of a stack map (for Java Micro Edition).
473:                if (expectedStackMapFrameOffset >= 0) {
474:                    offsetDelta -= expectedStackMapFrameOffset;
475:
476:                    expectedStackMapFrameOffset = stackMapFrameOffset + 1;
477:                }
478:
479:                stackMapFrame.u2offsetDelta = offsetDelta;
480:            }
481:
482:            public void visitSameOneFrame(Clazz clazz, Method method,
483:                    CodeAttribute codeAttribute, int offset,
484:                    SameOneFrame sameOneFrame) {
485:                // Remap the stack map frame offset.
486:                visitAnyStackMapFrame(clazz, method, codeAttribute, offset,
487:                        sameOneFrame);
488:
489:                // Remap the verification type offset.
490:                sameOneFrame.stackItemAccept(clazz, method, codeAttribute,
491:                        offset, this );
492:            }
493:
494:            public void visitMoreZeroFrame(Clazz clazz, Method method,
495:                    CodeAttribute codeAttribute, int offset,
496:                    MoreZeroFrame moreZeroFrame) {
497:                // Remap the stack map frame offset.
498:                visitAnyStackMapFrame(clazz, method, codeAttribute, offset,
499:                        moreZeroFrame);
500:
501:                // Remap the verification type offsets.
502:                moreZeroFrame.additionalVariablesAccept(clazz, method,
503:                        codeAttribute, offset, this );
504:            }
505:
506:            public void visitFullFrame(Clazz clazz, Method method,
507:                    CodeAttribute codeAttribute, int offset, FullFrame fullFrame) {
508:                // Remap the stack map frame offset.
509:                visitAnyStackMapFrame(clazz, method, codeAttribute, offset,
510:                        fullFrame);
511:
512:                // Remap the verification type offsets.
513:                fullFrame.variablesAccept(clazz, method, codeAttribute, offset,
514:                        this );
515:                fullFrame.stackAccept(clazz, method, codeAttribute, offset,
516:                        this );
517:            }
518:
519:            // Implementations for VerificationTypeVisitor.
520:
521:            public void visitAnyVerificationType(Clazz clazz, Method method,
522:                    CodeAttribute codeAttribute, int offset,
523:                    VerificationType verificationType) {
524:            }
525:
526:            public void visitUninitializedType(Clazz clazz, Method method,
527:                    CodeAttribute codeAttribute, int offset,
528:                    UninitializedType uninitializedType) {
529:                // Remap the offset of the 'new' instruction.
530:                uninitializedType.u2newInstructionOffset = remapInstructionOffset(uninitializedType.u2newInstructionOffset);
531:            }
532:
533:            // Implementations for LineNumberInfoVisitor.
534:
535:            public void visitLineNumberInfo(Clazz clazz, Method method,
536:                    CodeAttribute codeAttribute, LineNumberInfo lineNumberInfo) {
537:                // Remap the code offset.
538:                lineNumberInfo.u2startPC = remapInstructionOffset(lineNumberInfo.u2startPC);
539:            }
540:
541:            // Implementations for LocalVariableInfoVisitor.
542:
543:            public void visitLocalVariableInfo(Clazz clazz, Method method,
544:                    CodeAttribute codeAttribute,
545:                    LocalVariableInfo localVariableInfo) {
546:                // Remap the code offset and length.
547:                // TODO: The local variable frame might not be strictly preserved.
548:                int startPC = remapInstructionOffset(localVariableInfo.u2startPC);
549:                int endPC = remapInstructionOffset(localVariableInfo.u2startPC
550:                        + localVariableInfo.u2length);
551:
552:                localVariableInfo.u2startPC = startPC;
553:                localVariableInfo.u2length = endPC - startPC;
554:            }
555:
556:            // Implementations for LocalVariableTypeInfoVisitor.
557:
558:            public void visitLocalVariableTypeInfo(Clazz clazz, Method method,
559:                    CodeAttribute codeAttribute,
560:                    LocalVariableTypeInfo localVariableTypeInfo) {
561:                // Remap the code offset and length.
562:                // TODO: The local variable frame might not be strictly preserved.
563:                int startPC = remapInstructionOffset(localVariableTypeInfo.u2startPC);
564:                int endPC = remapInstructionOffset(localVariableTypeInfo.u2startPC
565:                        + localVariableTypeInfo.u2length);
566:
567:                localVariableTypeInfo.u2startPC = startPC;
568:                localVariableTypeInfo.u2length = endPC - startPC;
569:            }
570:
571:            // Small utility methods.
572:
573:            /**
574:             * Adjusts the given jump offsets for the instruction at the given offset.
575:             */
576:            private void remapJumpOffsets(int offset, int[] jumpOffsets) {
577:                for (int index = 0; index < jumpOffsets.length; index++) {
578:                    jumpOffsets[index] = remapBranchOffset(offset,
579:                            jumpOffsets[index]);
580:                }
581:            }
582:
583:            /**
584:             * Computes the new branch offset for the instruction at the given new offset
585:             * with the given old branch offset.
586:             */
587:            private int remapBranchOffset(int newInstructionOffset,
588:                    int branchOffset) {
589:                if (newInstructionOffset < 0
590:                        || newInstructionOffset > codeLength) {
591:                    throw new IllegalArgumentException(
592:                            "Invalid instruction offset ["
593:                                    + newInstructionOffset
594:                                    + "] in code with length [" + codeLength
595:                                    + "]");
596:                }
597:
598:                int oldInstructionOffset = oldInstructionOffsets[newInstructionOffset];
599:
600:                return remapInstructionOffset(oldInstructionOffset
601:                        + branchOffset)
602:                        - remapInstructionOffset(oldInstructionOffset);
603:            }
604:
605:            /**
606:             * Computes the new instruction offset for the instruction at the given old
607:             * offset.
608:             */
609:            private int remapInstructionOffset(int oldInstructionOffset) {
610:                if (oldInstructionOffset < 0
611:                        || oldInstructionOffset > codeFragmentLengths[level]) {
612:                    throw new IllegalArgumentException("Instruction offset ["
613:                            + oldInstructionOffset
614:                            + "] out of range in code fragment with length ["
615:                            + codeFragmentLengths[level] + "] at level "
616:                            + level);
617:                }
618:
619:                int newInstructionOffset = instructionOffsetMap[level][oldInstructionOffset];
620:                if (newInstructionOffset == INVALID) {
621:                    throw new IllegalArgumentException(
622:                            "Invalid instruction offset ["
623:                                    + oldInstructionOffset
624:                                    + "] in code fragment at level " + level);
625:                }
626:
627:                return newInstructionOffset;
628:            }
629:
630:            /**
631:             * Returns the given list of exceptions, without the ones that have empty
632:             * code blocks.
633:             */
634:            private int removeEmptyExceptions(ExceptionInfo[] exceptionInfos,
635:                    int exceptionInfoCount) {
636:                // Overwrite all empty exceptions.
637:                int newIndex = 0;
638:                for (int index = 0; index < exceptionInfoCount; index++) {
639:                    ExceptionInfo exceptionInfo = exceptionInfos[index];
640:                    if (exceptionInfo.u2startPC < exceptionInfo.u2endPC) {
641:                        exceptionInfos[newIndex++] = exceptionInfo;
642:                    }
643:                }
644:
645:                // Clear the unused array entries.
646:                for (int index = newIndex; index < exceptionInfoCount; index++) {
647:                    exceptionInfos[index] = null;
648:                }
649:
650:                return newIndex;
651:            }
652:
653:            /**
654:             * Returns the given list of line numbers, without the ones that have empty
655:             * code blocks or that exceed the code size.
656:             */
657:            private int removeEmptyLineNumbers(
658:                    LineNumberInfo[] lineNumberInfos, int lineNumberInfoCount,
659:                    int codeLength) {
660:                // Overwrite all empty line number entries.
661:                int newIndex = 0;
662:                for (int index = 0; index < lineNumberInfoCount; index++) {
663:                    LineNumberInfo lineNumberInfo = lineNumberInfos[index];
664:                    int startPC = lineNumberInfo.u2startPC;
665:                    if (startPC < codeLength
666:                            && (index == 0 || startPC > lineNumberInfos[index - 1].u2startPC)) {
667:                        lineNumberInfos[newIndex++] = lineNumberInfo;
668:                    }
669:                }
670:
671:                // Clear the unused array entries.
672:                for (int index = newIndex; index < lineNumberInfoCount; index++) {
673:                    lineNumberInfos[index] = null;
674:                }
675:
676:                return newIndex;
677:            }
678:
679:            /**
680:             * Returns the given list of local variables, without the ones that have empty
681:             * code blocks or that exceed the actual number of local variables.
682:             */
683:            private int removeEmptyLocalVariables(
684:                    LocalVariableInfo[] localVariableInfos,
685:                    int localVariableInfoCount, int maxLocals) {
686:                // Overwrite all empty local variable entries.
687:                int newIndex = 0;
688:                for (int index = 0; index < localVariableInfoCount; index++) {
689:                    LocalVariableInfo localVariableInfo = localVariableInfos[index];
690:                    if (localVariableInfo.u2length > 0
691:                            && localVariableInfo.u2index < maxLocals) {
692:                        localVariableInfos[newIndex++] = localVariableInfo;
693:                    }
694:                }
695:
696:                // Clear the unused array entries.
697:                for (int index = newIndex; index < localVariableInfoCount; index++) {
698:                    localVariableInfos[index] = null;
699:                }
700:
701:                return newIndex;
702:            }
703:
704:            /**
705:             * Returns the given list of local variable types, without the ones that
706:             * have empty code blocks or that exceed the actual number of local variables.
707:             */
708:            private int removeEmptyLocalVariableTypes(
709:                    LocalVariableTypeInfo[] localVariableTypeInfos,
710:                    int localVariableTypeInfoCount, int maxLocals) {
711:                // Overwrite all empty local variable type entries.
712:                int newIndex = 0;
713:                for (int index = 0; index < localVariableTypeInfoCount; index++) {
714:                    LocalVariableTypeInfo localVariableTypeInfo = localVariableTypeInfos[index];
715:                    if (localVariableTypeInfo.u2length > 0
716:                            && localVariableTypeInfo.u2index < maxLocals) {
717:                        localVariableTypeInfos[newIndex++] = localVariableTypeInfo;
718:                    }
719:                }
720:
721:                // Clear the unused array entries.
722:                for (int index = newIndex; index < localVariableTypeInfoCount; index++) {
723:                    localVariableTypeInfos[index] = null;
724:                }
725:
726:                return newIndex;
727:            }
728:
729:            private void println(String string1, String string2) {
730:                print(string1, string2);
731:
732:                System.out.println();
733:            }
734:
735:            private void print(String string1, String string2) {
736:                System.out.print(string1);
737:
738:                for (int index = 0; index < level; index++) {
739:                    System.out.print("  ");
740:                }
741:
742:                System.out.print(string2);
743:            }
744:
745:            public static void main(String[] args) {
746:                CodeAttributeComposer composer = new CodeAttributeComposer();
747:
748:                composer.beginCodeFragment(10);
749:                composer.appendInstruction(0, new SimpleInstruction(
750:                        InstructionConstants.OP_ICONST_0));
751:                composer.appendInstruction(1, new VariableInstruction(
752:                        InstructionConstants.OP_ISTORE, 0));
753:                composer.appendInstruction(2, new BranchInstruction(
754:                        InstructionConstants.OP_GOTO, 1));
755:
756:                composer.beginCodeFragment(10);
757:                composer.appendInstruction(0, new VariableInstruction(
758:                        InstructionConstants.OP_IINC, 0, 1));
759:                composer.appendInstruction(1, new VariableInstruction(
760:                        InstructionConstants.OP_ILOAD, 0));
761:                composer.appendInstruction(2, new SimpleInstruction(
762:                        InstructionConstants.OP_ICONST_5));
763:                composer.appendInstruction(3, new BranchInstruction(
764:                        InstructionConstants.OP_IFICMPLT, -3));
765:                composer.endCodeFragment();
766:
767:                composer.appendInstruction(3, new SimpleInstruction(
768:                        InstructionConstants.OP_RETURN));
769:                composer.endCodeFragment();
770:            }
771:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.