Source Code Cross Referenced for CodeIterator.java in  » Byte-Code » Javassist » javassist » bytecode » 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 » Byte Code » Javassist » javassist.bytecode 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         * Javassist, a Java-bytecode translator toolkit.
003:         * Copyright (C) 1999-2006 Shigeru Chiba. All Rights Reserved.
004:         *
005:         * The contents of this file are subject to the Mozilla Public License Version
006:         * 1.1 (the "License"); you may not use this file except in compliance with
007:         * the License.  Alternatively, the contents of this file may be used under
008:         * the terms of the GNU Lesser General Public License Version 2.1 or later.
009:         *
010:         * Software distributed under the License is distributed on an "AS IS" basis,
011:         * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
012:         * for the specific language governing rights and limitations under the
013:         * License.
014:         */
015:
016:        package javassist.bytecode;
017:
018:        /**
019:         * An iterator for editing a code attribute.
020:         *
021:         * <p>If there are multiple <code>CodeIterator</code>s referring to the
022:         * same <code>Code_attribute</code>, then inserting a gap by one
023:         * <code>CodeIterator</code> will break the other
024:         * <code>CodeIterator</code>.
025:         *
026:         * <p>This iterator does not provide <code>remove()</code>.
027:         * If a piece of code in a <code>Code_attribute</code> is unnecessary,
028:         * it should be overwritten with <code>NOP</code>.
029:         *
030:         * @see CodeAttribute#iterator()
031:         */
032:        public class CodeIterator implements  Opcode {
033:            protected CodeAttribute codeAttr;
034:            protected byte[] bytecode;
035:            protected int endPos;
036:            protected int currentPos;
037:
038:            protected CodeIterator(CodeAttribute ca) {
039:                codeAttr = ca;
040:                bytecode = ca.getCode();
041:                begin();
042:            }
043:
044:            /**
045:             * Moves to the first instruction.
046:             */
047:            public void begin() {
048:                currentPos = 0;
049:                endPos = getCodeLength();
050:            }
051:
052:            /**
053:             * Moves to the given index.
054:             *
055:             * <p>The index of the next instruction is set to the given index.
056:             * The successive call to <code>next()</code>
057:             * returns the index that has been given to <code>move()</code>.
058:             *
059:             * <p>Note that the index is into the byte array returned by
060:             * <code>get().getCode()</code>.
061:             *
062:             * @see CodeAttribute#getCode()
063:             */
064:            public void move(int index) {
065:                currentPos = index;
066:            }
067:
068:            /**
069:             * Returns a Code attribute read with this iterator.
070:             */
071:            public CodeAttribute get() {
072:                return codeAttr;
073:            }
074:
075:            /**
076:             * Returns <code>code_length</code> of <code>Code_attribute</code>.
077:             */
078:            public int getCodeLength() {
079:                return bytecode.length;
080:            }
081:
082:            /**
083:             * Returns the unsigned 8bit value at the given index.
084:             */
085:            public int byteAt(int index) {
086:                return bytecode[index] & 0xff;
087:            }
088:
089:            /**
090:             * Writes an 8bit value at the given index.
091:             */
092:            public void writeByte(int value, int index) {
093:                bytecode[index] = (byte) value;
094:            }
095:
096:            /**
097:             * Returns the unsigned 16bit value at the given index.
098:             */
099:            public int u16bitAt(int index) {
100:                return ByteArray.readU16bit(bytecode, index);
101:            }
102:
103:            /**
104:             * Returns the signed 16bit value at the given index.
105:             */
106:            public int s16bitAt(int index) {
107:                return ByteArray.readS16bit(bytecode, index);
108:            }
109:
110:            /**
111:             * Writes a 16 bit integer at the index.
112:             */
113:            public void write16bit(int value, int index) {
114:                ByteArray.write16bit(value, bytecode, index);
115:            }
116:
117:            /**
118:             * Returns the signed 32bit value at the given index.
119:             */
120:            public int s32bitAt(int index) {
121:                return ByteArray.read32bit(bytecode, index);
122:            }
123:
124:            /**
125:             * Writes a 32bit integer at the index.
126:             */
127:            public void write32bit(int value, int index) {
128:                ByteArray.write32bit(value, bytecode, index);
129:            }
130:
131:            /**
132:             * Writes a byte array at the index.
133:             *
134:             * @param code	may be a zero-length array.
135:             */
136:            public void write(byte[] code, int index) {
137:                int len = code.length;
138:                for (int j = 0; j < len; ++j)
139:                    bytecode[index++] = code[j];
140:            }
141:
142:            /**
143:             * Returns true if there is more instructions.
144:             */
145:            public boolean hasNext() {
146:                return currentPos < endPos;
147:            }
148:
149:            /**
150:             * Returns the index of the next instruction
151:             * (not the operand following the current opcode).
152:             *
153:             * <p>Note that the index is into the byte array returned by
154:             * <code>get().getCode()</code>.
155:             *
156:             * @see CodeAttribute#getCode()
157:             * @see CodeIterator#byteAt(int)
158:             */
159:            public int next() throws BadBytecode {
160:                int pos = currentPos;
161:                currentPos = nextOpcode(bytecode, pos);
162:                return pos;
163:            }
164:
165:            /**
166:             * Obtains the value that the next call
167:             * to <code>next()</code> will return.
168:             *
169:             * <p>This method is side-effects free.
170:             * Successive calls to <code>lookAhead()</code> return the
171:             * same value until <code>next()</code> is called.
172:             */
173:            public int lookAhead() {
174:                return currentPos;
175:            }
176:
177:            /**
178:             * Moves to the instruction for
179:             * either <code>super()</code> or <code>this()</code>.
180:             *
181:             * <p>This method skips all the instructions for computing arguments
182:             * to <code>super()</code> or <code>this()</code>, which should be
183:             * placed at the beginning of a constructor body.
184:             *
185:             * <p>This method returns the index of INVOKESPECIAL instruction
186:             * executing <code>super()</code> or <code>this()</code>.
187:             * A successive call to <code>next()</code> returns the
188:             * index of the next instruction following that INVOKESPECIAL.
189:             *
190:             * <p>This method works only for a constructor.
191:             *
192:             * @return  the index of the INVOKESPECIAL instruction, or -1
193:             *          if a constructor invocation is not found.
194:             */
195:            public int skipConstructor() throws BadBytecode {
196:                return skipSuperConstructor0(-1);
197:            }
198:
199:            /**
200:             * Moves to the instruction for <code>super()</code>.
201:             *
202:             * <p>This method skips all the instructions for computing arguments to
203:             * <code>super()</code>, which should be
204:             * placed at the beginning of a constructor body.
205:             *
206:             * <p>This method returns the index of INVOKESPECIAL instruction
207:             * executing <code>super()</code>.
208:             * A successive call to <code>next()</code> returns the
209:             * index of the next instruction following that INVOKESPECIAL.
210:             *
211:             * <p>This method works only for a constructor.
212:             *
213:             * @return  the index of the INVOKESPECIAL instruction, or -1
214:             *          if a super constructor invocation is not found
215:             *          but <code>this()</code> is found.
216:             */
217:            public int skipSuperConstructor() throws BadBytecode {
218:                return skipSuperConstructor0(0);
219:            }
220:
221:            /**
222:             * Moves to the instruction for <code>this()</code>.
223:             *
224:             * <p>This method skips all the instructions for computing arguments to
225:             * <code>this()</code>, which should be
226:             * placed at the beginning of a constructor body.
227:             *
228:             * <p>This method returns the index of INVOKESPECIAL instruction
229:             * executing <code>this()</code>.
230:             * A successive call to <code>next()</code> returns the
231:             * index of the next instruction following that INVOKESPECIAL.
232:             *
233:             * <p>This method works only for a constructor.
234:             *
235:             * @return  the index of the INVOKESPECIAL instruction, or -1
236:             *          if a explicit constructor invocation is not found
237:             *          but <code>super()</code> is found.
238:             */
239:            public int skipThisConstructor() throws BadBytecode {
240:                return skipSuperConstructor0(1);
241:            }
242:
243:            /* skipSuper        1: this(), 0: super(), -1: both.
244:             */
245:            private int skipSuperConstructor0(int skipThis) throws BadBytecode {
246:                begin();
247:                ConstPool cp = codeAttr.getConstPool();
248:                String this ClassName = codeAttr.getDeclaringClass();
249:                int nested = 0;
250:                while (hasNext()) {
251:                    int index = next();
252:                    int c = byteAt(index);
253:                    if (c == NEW)
254:                        ++nested;
255:                    else if (c == INVOKESPECIAL) {
256:                        int mref = ByteArray.readU16bit(bytecode, index + 1);
257:                        if (cp.getMethodrefName(mref).equals(
258:                                MethodInfo.nameInit))
259:                            if (--nested < 0) {
260:                                if (skipThis < 0)
261:                                    return index;
262:
263:                                String cname = cp.getMethodrefClassName(mref);
264:                                if (cname.equals(this ClassName) == (skipThis > 0))
265:                                    return index;
266:                                else
267:                                    break;
268:                            }
269:                    }
270:                }
271:
272:                begin();
273:                return -1;
274:            }
275:
276:            /**
277:             * Inserts the given bytecode sequence
278:             * before the next instruction that would be returned by
279:             * <code>next()</code> (not before the instruction returned
280:             * by tha last call to <code>next()</code>).
281:             * Branch offsets and the exception table are also updated.
282:             *
283:             * <p>If the next instruction is at the beginning of a block statement,
284:             * then the bytecode is inserted within that block.
285:             *
286:             * <p>An extra gap may be inserted at the end of the inserted
287:             * bytecode sequence for adjusting alignment if the code attribute
288:             * includes <code>LOOKUPSWITCH</code> or <code>TABLESWITCH</code>.
289:             *
290:             * @param code      inserted bytecode sequence.
291:             * @return          the index indicating the first byte of the
292:             *                  inserted byte sequence.
293:             */
294:            public int insert(byte[] code) throws BadBytecode {
295:                int pos = currentPos;
296:                insert0(currentPos, code, false);
297:                return pos;
298:            }
299:
300:            /**
301:             * Inserts the given bytecode sequence
302:             * before the instruction at the given index <code>pos</code>.
303:             * Branch offsets and the exception table are also updated.
304:             *
305:             * <p>If the instruction at the given index is at the beginning
306:             * of a block statement,
307:             * then the bytecode is inserted within that block.
308:             *
309:             * <p>An extra gap may be inserted at the end of the inserted
310:             * bytecode sequence for adjusting alignment if the code attribute
311:             * includes <code>LOOKUPSWITCH</code> or <code>TABLESWITCH</code>.
312:             *
313:             * @param pos       the index at which a byte sequence is inserted.
314:             * @param code      inserted bytecode sequence.
315:             */
316:            public void insert(int pos, byte[] code) throws BadBytecode {
317:                insert0(pos, code, false);
318:            }
319:
320:            /**
321:             * Inserts the given bytecode sequence exclusively
322:             * before the next instruction that would be returned by
323:             * <code>next()</code> (not before the instruction returned
324:             * by tha last call to <code>next()</code>).
325:             * Branch offsets and the exception table are also updated.
326:             *
327:             * <p>If the next instruction is at the beginning of a block statement,
328:             * then the bytecode is excluded from that block.
329:             *
330:             * <p>An extra gap may be inserted at the end of the inserted
331:             * bytecode sequence for adjusting alignment if the code attribute
332:             * includes <code>LOOKUPSWITCH</code> or <code>TABLESWITCH</code>.
333:             *
334:             * @param code      inserted bytecode sequence.
335:             * @return          the index indicating the first byte of the
336:             *                  inserted byte sequence.
337:             */
338:            public int insertEx(byte[] code) throws BadBytecode {
339:                int pos = currentPos;
340:                insert0(currentPos, code, true);
341:                return pos;
342:            }
343:
344:            /**
345:             * Inserts the given bytecode sequence exclusively
346:             * before the instruction at the given index <code>pos</code>.
347:             * Branch offsets and the exception table are also updated.
348:             *
349:             * <p>If the instruction at the given index is at the beginning
350:             * of a block statement,
351:             * then the bytecode is excluded from that block.
352:             *
353:             * <p>An extra gap may be inserted at the end of the inserted
354:             * bytecode sequence for adjusting alignment if the code attribute
355:             * includes <code>LOOKUPSWITCH</code> or <code>TABLESWITCH</code>.
356:             *
357:             * @param pos       the index at which a byte sequence is inserted.
358:             * @param code      inserted bytecode sequence.
359:             */
360:            public void insertEx(int pos, byte[] code) throws BadBytecode {
361:                insert0(pos, code, true);
362:            }
363:
364:            private void insert0(int pos, byte[] code, boolean exclusive)
365:                    throws BadBytecode {
366:                int len = code.length;
367:                if (len <= 0)
368:                    return;
369:
370:                insertGapCore(pos, len, exclusive); // currentPos will change.
371:                for (int j = 0; j < len; ++j)
372:                    bytecode[pos++] = code[j];
373:            }
374:
375:            /**
376:             * Inserts a gap
377:             * before the next instruction that would be returned by
378:             * <code>next()</code> (not before the instruction returned
379:             * by tha last call to <code>next()</code>).
380:             * Branch offsets and the exception table are also updated.
381:             * The inserted gap is filled with NOP.  The gap length may be
382:             * extended to a multiple of 4.
383:             *
384:             * <p>If the next instruction is at the beginning of a block statement,
385:             * then the gap is inserted within that block.
386:             *
387:             * @param length            gap length
388:             * @return  the index indicating the first byte of the inserted gap.
389:             */
390:            public int insertGap(int length) throws BadBytecode {
391:                int pos = currentPos;
392:                insertGapCore(currentPos, length, false);
393:                return pos;
394:            }
395:
396:            /**
397:             * Inserts a gap in front of the instruction at the given
398:             * index <code>pos</code>.
399:             * Branch offsets and the exception table are also updated.
400:             * The inserted gap is filled with NOP.  The gap length may be
401:             * extended to a multiple of 4.
402:             *
403:             * <p>If the instruction at the given index is at the beginning
404:             * of a block statement,
405:             * then the gap is inserted within that block.
406:             *
407:             * @param pos               the index at which a gap is inserted.
408:             * @param length            gap length.
409:             * @return the length of the inserted gap.
410:             *          It might be bigger than <code>length</code>.
411:             */
412:            public int insertGap(int pos, int length) throws BadBytecode {
413:                return insertGapCore(pos, length, false);
414:            }
415:
416:            /**
417:             * Inserts an exclusive gap
418:             * before the next instruction that would be returned by
419:             * <code>next()</code> (not before the instruction returned
420:             * by tha last call to <code>next()</code>).
421:             * Branch offsets and the exception table are also updated.
422:             * The inserted gap is filled with NOP.  The gap length may be
423:             * extended to a multiple of 4.
424:             *
425:             * <p>If the next instruction is at the beginning of a block statement,
426:             * then the gap is excluded from that block.
427:             *
428:             * @param length            gap length
429:             * @return  the index indicating the first byte of the inserted gap.
430:             */
431:            public int insertExGap(int length) throws BadBytecode {
432:                int pos = currentPos;
433:                insertGapCore(currentPos, length, true);
434:                return pos;
435:            }
436:
437:            /**
438:             * Inserts an exclusive gap in front of the instruction at the given
439:             * index <code>pos</code>.
440:             * Branch offsets and the exception table are also updated.
441:             * The inserted gap is filled with NOP.  The gap length may be
442:             * extended to a multiple of 4.
443:             *
444:             * <p>If the instruction at the given index is at the beginning
445:             * of a block statement,
446:             * then the gap is excluded from that block.
447:             *
448:             * @param pos               the index at which a gap is inserted.
449:             * @param length            gap length.
450:             * @return the length of the inserted gap.
451:             *          It might be bigger than <code>length</code>.
452:             */
453:            public int insertExGap(int pos, int length) throws BadBytecode {
454:                return insertGapCore(pos, length, true);
455:            }
456:
457:            /**
458:             * @return the length of the really inserted gap.
459:             */
460:            private int insertGapCore(int pos, int length, boolean exclusive)
461:                    throws BadBytecode {
462:                if (length <= 0)
463:                    return 0;
464:
465:                int cur = currentPos;
466:                byte[] c = insertGap(bytecode, pos, length, exclusive, get()
467:                        .getExceptionTable(), codeAttr);
468:                int length2 = c.length - bytecode.length;
469:                if (cur >= pos)
470:                    currentPos = cur + length2;
471:
472:                codeAttr.setCode(c);
473:                bytecode = c;
474:                endPos = getCodeLength();
475:                updateCursors(pos, length2);
476:                return length2;
477:            }
478:
479:            /**
480:             * Is called when a gap is inserted.  The default implementation is empty.
481:             * A subclass can override this method so that cursors will be updated.
482:             *
483:             * @param pos           the position where a gap is inserted.
484:             * @param length        the length of the gap.
485:             */
486:            protected void updateCursors(int pos, int length) {
487:                // empty
488:            }
489:
490:            /**
491:             * Copies and inserts the entries in the given exception table
492:             * at the beginning of the exception table in the code attribute
493:             * edited by this object.
494:             *
495:             * @param offset    the value added to the code positions included
496:             *                          in the entries.
497:             */
498:            public void insert(ExceptionTable et, int offset) {
499:                codeAttr.getExceptionTable().add(0, et, offset);
500:            }
501:
502:            /**
503:             * Appends the given bytecode sequence at the end.
504:             *
505:             * @param code      the bytecode appended.
506:             * @return  the position of the first byte of the appended bytecode.
507:             */
508:            public int append(byte[] code) {
509:                int size = getCodeLength();
510:                int len = code.length;
511:                if (len <= 0)
512:                    return size;
513:
514:                appendGap(len);
515:                byte[] dest = bytecode;
516:                for (int i = 0; i < len; ++i)
517:                    dest[i + size] = code[i];
518:
519:                return size;
520:            }
521:
522:            /**
523:             * Appends a gap at the end of the bytecode sequence.
524:             *
525:             * @param gapLength            gap length
526:             */
527:            public void appendGap(int gapLength) {
528:                byte[] code = bytecode;
529:                int codeLength = code.length;
530:                byte[] newcode = new byte[codeLength + gapLength];
531:
532:                int i;
533:                for (i = 0; i < codeLength; ++i)
534:                    newcode[i] = code[i];
535:
536:                for (i = codeLength; i < codeLength + gapLength; ++i)
537:                    newcode[i] = NOP;
538:
539:                codeAttr.setCode(newcode);
540:                bytecode = newcode;
541:                endPos = getCodeLength();
542:            }
543:
544:            /**
545:             * Copies and appends the entries in the given exception table
546:             * at the end of the exception table in the code attribute
547:             * edited by this object.
548:             *
549:             * @param offset    the value added to the code positions included
550:             *                          in the entries.
551:             */
552:            public void append(ExceptionTable et, int offset) {
553:                ExceptionTable table = codeAttr.getExceptionTable();
554:                table.add(table.size(), et, offset);
555:            }
556:
557:            /* opcodeLegth is used for implementing nextOpcode().
558:             */
559:            private static final int opcodeLength[] = { 1, 1, 1, 1, 1, 1, 1, 1,
560:                    1, 1, 1, 1, 1, 1, 1, 1, 2, 3, 2, 3, 3, 2, 2, 2, 2, 2, 1, 1,
561:                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
562:                    1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1,
563:                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
564:                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
565:                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
566:                    1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
567:                    1, 1, 1, 1, 1, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
568:                    3, 2, 0, 0, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 3, 3, 3, 5, 0, 3,
569:                    2, 3, 1, 1, 3, 3, 1, 1, 0, 4, 3, 3, 5, 5 };
570:
571:            // 0 .. UNUSED (186), LOOKUPSWITCH, TABLESWITCH, WIDE
572:
573:            /**
574:             * Calculates the index of the next opcode.
575:             */
576:            static int nextOpcode(byte[] code, int index) throws BadBytecode {
577:                int opcode;
578:                try {
579:                    opcode = code[index] & 0xff;
580:                } catch (IndexOutOfBoundsException e) {
581:                    throw new BadBytecode("invalid opcode address");
582:                }
583:
584:                try {
585:                    int len = opcodeLength[opcode];
586:                    if (len > 0)
587:                        return index + len;
588:                    else if (opcode == WIDE)
589:                        if (code[index + 1] == (byte) IINC) // WIDE IINC
590:                            return index + 6;
591:                        else
592:                            return index + 4; // WIDE ...
593:                    else {
594:                        int index2 = (index & ~3) + 8;
595:                        if (opcode == LOOKUPSWITCH) {
596:                            int npairs = ByteArray.read32bit(code, index2);
597:                            return index2 + npairs * 8 + 4;
598:                        } else if (opcode == TABLESWITCH) {
599:                            int low = ByteArray.read32bit(code, index2);
600:                            int high = ByteArray.read32bit(code, index2 + 4);
601:                            return index2 + (high - low + 1) * 4 + 8;
602:                        }
603:                        // else
604:                        //     throw new BadBytecode(opcode);
605:                    }
606:                } catch (IndexOutOfBoundsException e) {
607:                }
608:
609:                // opcode is UNUSED or an IndexOutOfBoundsException was thrown.
610:                throw new BadBytecode(opcode);
611:            }
612:
613:            // methods for implementing insertGap().
614:
615:            /* If "where" is the beginning of a block statement, then the inserted
616:             * gap is also included in the block statement.
617:             * "where" must indicate the first byte of an opcode.
618:             * The inserted gap is filled with NOP.  gapLength may be extended to
619:             * a multiple of 4.
620:             */
621:            static byte[] insertGap(byte[] code, int where, int gapLength,
622:                    boolean exclusive, ExceptionTable etable, CodeAttribute ca)
623:                    throws BadBytecode {
624:                if (gapLength <= 0)
625:                    return code;
626:
627:                try {
628:                    return insertGap0(code, where, gapLength, exclusive,
629:                            etable, ca);
630:                } catch (AlignmentException e) {
631:                    try {
632:                        return insertGap0(code, where, (gapLength + 3) & ~3,
633:                                exclusive, etable, ca);
634:                    } catch (AlignmentException e2) {
635:                        throw new RuntimeException("fatal error?");
636:                    }
637:                }
638:            }
639:
640:            private static byte[] insertGap0(byte[] code, int where,
641:                    int gapLength, boolean exclusive, ExceptionTable etable,
642:                    CodeAttribute ca) throws BadBytecode, AlignmentException {
643:                int codeLength = code.length;
644:                byte[] newcode = new byte[codeLength + gapLength];
645:                insertGap2(code, where, gapLength, codeLength, newcode,
646:                        exclusive);
647:                etable.shiftPc(where, gapLength, exclusive);
648:                LineNumberAttribute na = (LineNumberAttribute) ca
649:                        .getAttribute(LineNumberAttribute.tag);
650:                if (na != null)
651:                    na.shiftPc(where, gapLength, exclusive);
652:
653:                LocalVariableAttribute va = (LocalVariableAttribute) ca
654:                        .getAttribute(LocalVariableAttribute.tag);
655:                if (va != null)
656:                    va.shiftPc(where, gapLength, exclusive);
657:
658:                LocalVariableAttribute vta = (LocalVariableAttribute) ca
659:                        .getAttribute(LocalVariableAttribute.typeTag);
660:                if (vta != null)
661:                    vta.shiftPc(where, gapLength, exclusive);
662:
663:                return newcode;
664:            }
665:
666:            private static void insertGap2(byte[] code, int where,
667:                    int gapLength, int endPos, byte[] newcode, boolean exclusive)
668:                    throws BadBytecode, AlignmentException {
669:                int nextPos;
670:                int i = 0;
671:                int j = 0;
672:                for (; i < endPos; i = nextPos) {
673:                    if (i == where) {
674:                        int j2 = j + gapLength;
675:                        while (j < j2)
676:                            newcode[j++] = NOP;
677:                    }
678:
679:                    nextPos = nextOpcode(code, i);
680:                    int inst = code[i] & 0xff;
681:                    // if<cond>, if_icmp<cond>, if_acmp<cond>, goto, jsr
682:                    if ((153 <= inst && inst <= 168) || inst == IFNULL
683:                            || inst == IFNONNULL) {
684:                        /* 2bytes *signed* offset */
685:                        int offset = (code[i + 1] << 8) | (code[i + 2] & 0xff);
686:                        offset = newOffset(i, offset, where, gapLength,
687:                                exclusive);
688:                        newcode[j] = code[i];
689:                        ByteArray.write16bit(offset, newcode, j + 1);
690:                        j += 3;
691:                    } else if (inst == GOTO_W || inst == JSR_W) {
692:                        /* 4bytes offset */
693:                        int offset = ByteArray.read32bit(code, i + 1);
694:                        offset = newOffset(i, offset, where, gapLength,
695:                                exclusive);
696:                        newcode[j++] = code[i];
697:                        ByteArray.write32bit(offset, newcode, j);
698:                        j += 4;
699:                    } else if (inst == TABLESWITCH) {
700:                        if (i != j && (gapLength & 3) != 0)
701:                            throw new AlignmentException();
702:
703:                        int i0 = i;
704:                        int i2 = (i & ~3) + 4; // 0-3 byte padding
705:                        while (i0 < i2)
706:                            newcode[j++] = code[i0++];
707:
708:                        int defaultbyte = newOffset(i, ByteArray.read32bit(
709:                                code, i2), where, gapLength, exclusive);
710:                        ByteArray.write32bit(defaultbyte, newcode, j);
711:                        int lowbyte = ByteArray.read32bit(code, i2 + 4);
712:                        ByteArray.write32bit(lowbyte, newcode, j + 4);
713:                        int highbyte = ByteArray.read32bit(code, i2 + 8);
714:                        ByteArray.write32bit(highbyte, newcode, j + 8);
715:                        j += 12;
716:                        i0 = i2 + 12;
717:                        i2 = i0 + (highbyte - lowbyte + 1) * 4;
718:                        while (i0 < i2) {
719:                            int offset = newOffset(i, ByteArray.read32bit(code,
720:                                    i0), where, gapLength, exclusive);
721:                            ByteArray.write32bit(offset, newcode, j);
722:                            j += 4;
723:                            i0 += 4;
724:                        }
725:                    } else if (inst == LOOKUPSWITCH) {
726:                        if (i != j && (gapLength & 3) != 0)
727:                            throw new AlignmentException();
728:
729:                        int i0 = i;
730:                        int i2 = (i & ~3) + 4; // 0-3 byte padding
731:                        while (i0 < i2)
732:                            newcode[j++] = code[i0++];
733:
734:                        int defaultbyte = newOffset(i, ByteArray.read32bit(
735:                                code, i2), where, gapLength, exclusive);
736:                        ByteArray.write32bit(defaultbyte, newcode, j);
737:                        int npairs = ByteArray.read32bit(code, i2 + 4);
738:                        ByteArray.write32bit(npairs, newcode, j + 4);
739:                        j += 8;
740:                        i0 = i2 + 8;
741:                        i2 = i0 + npairs * 8;
742:                        while (i0 < i2) {
743:                            ByteArray.copy32bit(code, i0, newcode, j);
744:                            int offset = newOffset(i, ByteArray.read32bit(code,
745:                                    i0 + 4), where, gapLength, exclusive);
746:                            ByteArray.write32bit(offset, newcode, j + 4);
747:                            j += 8;
748:                            i0 += 8;
749:                        }
750:                    } else
751:                        while (i < nextPos)
752:                            newcode[j++] = code[i++];
753:                }
754:            }
755:
756:            private static int newOffset(int i, int offset, int where,
757:                    int gapLength, boolean exclusive) {
758:                int target = i + offset;
759:                if (i < where) {
760:                    if (where < target || (exclusive && where == target))
761:                        offset += gapLength;
762:                } else if (target < where || (!exclusive && where == target))
763:                    offset -= gapLength;
764:
765:                return offset;
766:            }
767:        }
768:
769:        class AlignmentException extends Exception {
770:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.