Source Code Cross Referenced for MethodAccessorGenerator.java in  » 6.0-JDK-Modules-sun » reflect » sun » reflect » 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 » 6.0 JDK Modules sun » reflect » sun.reflect 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         * Copyright 2001 Sun Microsystems, Inc.  All Rights Reserved.
003:         * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004:         *
005:         * This code is free software; you can redistribute it and/or modify it
006:         * under the terms of the GNU General Public License version 2 only, as
007:         * published by the Free Software Foundation.  Sun designates this
008:         * particular file as subject to the "Classpath" exception as provided
009:         * by Sun in the LICENSE file that accompanied this code.
010:         *
011:         * This code is distributed in the hope that it will be useful, but WITHOUT
012:         * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013:         * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
014:         * version 2 for more details (a copy is included in the LICENSE file that
015:         * accompanied this code).
016:         *
017:         * You should have received a copy of the GNU General Public License version
018:         * 2 along with this work; if not, write to the Free Software Foundation,
019:         * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020:         *
021:         * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022:         * CA 95054 USA or visit www.sun.com if you need additional information or
023:         * have any questions.
024:         */
025:
026:        package sun.reflect;
027:
028:        import java.lang.reflect.*;
029:        import java.security.AccessController;
030:        import java.security.PrivilegedAction;
031:        import sun.misc.Unsafe;
032:
033:        /** Generator for sun.reflect.MethodAccessor and
034:         sun.reflect.ConstructorAccessor objects using bytecodes to
035:         implement reflection. A java.lang.reflect.Method or
036:         java.lang.reflect.Constructor object can delegate its invoke or
037:         newInstance method to an accessor using native code or to one
038:         generated by this class. (Methods and Constructors were merged
039:         together in this class to ensure maximum code sharing.) */
040:
041:        class MethodAccessorGenerator extends AccessorGenerator {
042:
043:            private static final short NUM_BASE_CPOOL_ENTRIES = (short) 12;
044:            // One for invoke() plus one for constructor
045:            private static final short NUM_METHODS = (short) 2;
046:            // Only used if forSerialization is true
047:            private static final short NUM_SERIALIZATION_CPOOL_ENTRIES = (short) 2;
048:
049:            private static volatile int methodSymnum = 0;
050:            private static volatile int constructorSymnum = 0;
051:            private static volatile int serializationConstructorSymnum = 0;
052:
053:            private Class declaringClass;
054:            private Class[] parameterTypes;
055:            private Class returnType;
056:            private boolean isConstructor;
057:            private boolean forSerialization;
058:
059:            private short targetMethodRef;
060:            private short invokeIdx;
061:            private short invokeDescriptorIdx;
062:            // Constant pool index of CONSTANT_Class_info for first
063:            // non-primitive parameter type. Should be incremented by 2.
064:            private short nonPrimitiveParametersBaseIdx;
065:
066:            MethodAccessorGenerator() {
067:            }
068:
069:            /** This routine is not thread-safe */
070:            public MethodAccessor generateMethod(Class declaringClass,
071:                    String name, Class[] parameterTypes, Class returnType,
072:                    Class[] checkedExceptions, int modifiers) {
073:                return (MethodAccessor) generate(declaringClass, name,
074:                        parameterTypes, returnType, checkedExceptions,
075:                        modifiers, false, false, null);
076:            }
077:
078:            /** This routine is not thread-safe */
079:            public ConstructorAccessor generateConstructor(
080:                    Class declaringClass, Class[] parameterTypes,
081:                    Class[] checkedExceptions, int modifiers) {
082:                return (ConstructorAccessor) generate(declaringClass, "<init>",
083:                        parameterTypes, Void.TYPE, checkedExceptions,
084:                        modifiers, true, false, null);
085:            }
086:
087:            /** This routine is not thread-safe */
088:            public SerializationConstructorAccessorImpl generateSerializationConstructor(
089:                    Class declaringClass, Class[] parameterTypes,
090:                    Class[] checkedExceptions, int modifiers,
091:                    Class targetConstructorClass) {
092:                return (SerializationConstructorAccessorImpl) generate(
093:                        declaringClass, "<init>", parameterTypes, Void.TYPE,
094:                        checkedExceptions, modifiers, true, true,
095:                        targetConstructorClass);
096:            }
097:
098:            /** This routine is not thread-safe */
099:            private MagicAccessorImpl generate(final Class declaringClass,
100:                    String name, Class[] parameterTypes, Class returnType,
101:                    Class[] checkedExceptions, int modifiers,
102:                    boolean isConstructor, boolean forSerialization,
103:                    Class serializationTargetClass) {
104:                ByteVector vec = ByteVectorFactory.create();
105:                asm = new ClassFileAssembler(vec);
106:                this .declaringClass = declaringClass;
107:                this .parameterTypes = parameterTypes;
108:                this .returnType = returnType;
109:                this .modifiers = modifiers;
110:                this .isConstructor = isConstructor;
111:                this .forSerialization = forSerialization;
112:
113:                asm.emitMagicAndVersion();
114:
115:                // Constant pool entries:
116:                // ( * = Boxing information: optional)
117:                // (+  = Shared entries provided by AccessorGenerator)
118:                // (^  = Only present if generating SerializationConstructorAccessor)
119:                //     [UTF-8] [This class's name]
120:                //     [CONSTANT_Class_info] for above
121:                //     [UTF-8] "sun/reflect/{MethodAccessorImpl,ConstructorAccessorImpl,SerializationConstructorAccessorImpl}"
122:                //     [CONSTANT_Class_info] for above
123:                //     [UTF-8] [Target class's name]
124:                //     [CONSTANT_Class_info] for above
125:                // ^   [UTF-8] [Serialization: Class's name in which to invoke constructor]
126:                // ^   [CONSTANT_Class_info] for above
127:                //     [UTF-8] target method or constructor name
128:                //     [UTF-8] target method or constructor signature
129:                //     [CONSTANT_NameAndType_info] for above
130:                //     [CONSTANT_Methodref_info or CONSTANT_InterfaceMethodref_info] for target method
131:                //     [UTF-8] "invoke" or "newInstance"
132:                //     [UTF-8] invoke or newInstance descriptor
133:                //     [UTF-8] descriptor for type of non-primitive parameter 1
134:                //     [CONSTANT_Class_info] for type of non-primitive parameter 1
135:                //     ...
136:                //     [UTF-8] descriptor for type of non-primitive parameter n
137:                //     [CONSTANT_Class_info] for type of non-primitive parameter n
138:                // +   [UTF-8] "java/lang/Exception"
139:                // +   [CONSTANT_Class_info] for above
140:                // +   [UTF-8] "java/lang/ClassCastException"
141:                // +   [CONSTANT_Class_info] for above
142:                // +   [UTF-8] "java/lang/NullPointerException"
143:                // +   [CONSTANT_Class_info] for above
144:                // +   [UTF-8] "java/lang/IllegalArgumentException"
145:                // +   [CONSTANT_Class_info] for above
146:                // +   [UTF-8] "java/lang/InvocationTargetException"
147:                // +   [CONSTANT_Class_info] for above
148:                // +   [UTF-8] "<init>"
149:                // +   [UTF-8] "()V"
150:                // +   [CONSTANT_NameAndType_info] for above
151:                // +   [CONSTANT_Methodref_info] for NullPointerException's constructor
152:                // +   [CONSTANT_Methodref_info] for IllegalArgumentException's constructor
153:                // +   [UTF-8] "(Ljava/lang/String;)V"
154:                // +   [CONSTANT_NameAndType_info] for "<init>(Ljava/lang/String;)V"
155:                // +   [CONSTANT_Methodref_info] for IllegalArgumentException's constructor taking a String
156:                // +   [UTF-8] "(Ljava/lang/Throwable;)V"
157:                // +   [CONSTANT_NameAndType_info] for "<init>(Ljava/lang/Throwable;)V"
158:                // +   [CONSTANT_Methodref_info] for InvocationTargetException's constructor
159:                // +   [CONSTANT_Methodref_info] for "super()"
160:                // +   [UTF-8] "java/lang/Object"
161:                // +   [CONSTANT_Class_info] for above
162:                // +   [UTF-8] "toString"
163:                // +   [UTF-8] "()Ljava/lang/String;"
164:                // +   [CONSTANT_NameAndType_info] for "toString()Ljava/lang/String;"
165:                // +   [CONSTANT_Methodref_info] for Object's toString method
166:                // +   [UTF-8] "Code"
167:                // +   [UTF-8] "Exceptions"
168:                //  *  [UTF-8] "java/lang/Boolean"
169:                //  *  [CONSTANT_Class_info] for above
170:                //  *  [UTF-8] "(Z)V"
171:                //  *  [CONSTANT_NameAndType_info] for above
172:                //  *  [CONSTANT_Methodref_info] for above
173:                //  *  [UTF-8] "booleanValue"
174:                //  *  [UTF-8] "()Z"
175:                //  *  [CONSTANT_NameAndType_info] for above
176:                //  *  [CONSTANT_Methodref_info] for above
177:                //  *  [UTF-8] "java/lang/Byte"
178:                //  *  [CONSTANT_Class_info] for above
179:                //  *  [UTF-8] "(B)V"
180:                //  *  [CONSTANT_NameAndType_info] for above
181:                //  *  [CONSTANT_Methodref_info] for above
182:                //  *  [UTF-8] "byteValue"
183:                //  *  [UTF-8] "()B"
184:                //  *  [CONSTANT_NameAndType_info] for above
185:                //  *  [CONSTANT_Methodref_info] for above
186:                //  *  [UTF-8] "java/lang/Character"
187:                //  *  [CONSTANT_Class_info] for above
188:                //  *  [UTF-8] "(C)V"
189:                //  *  [CONSTANT_NameAndType_info] for above
190:                //  *  [CONSTANT_Methodref_info] for above
191:                //  *  [UTF-8] "charValue"
192:                //  *  [UTF-8] "()C"
193:                //  *  [CONSTANT_NameAndType_info] for above
194:                //  *  [CONSTANT_Methodref_info] for above
195:                //  *  [UTF-8] "java/lang/Double"
196:                //  *  [CONSTANT_Class_info] for above
197:                //  *  [UTF-8] "(D)V"
198:                //  *  [CONSTANT_NameAndType_info] for above
199:                //  *  [CONSTANT_Methodref_info] for above
200:                //  *  [UTF-8] "doubleValue"
201:                //  *  [UTF-8] "()D"
202:                //  *  [CONSTANT_NameAndType_info] for above
203:                //  *  [CONSTANT_Methodref_info] for above
204:                //  *  [UTF-8] "java/lang/Float"
205:                //  *  [CONSTANT_Class_info] for above
206:                //  *  [UTF-8] "(F)V"
207:                //  *  [CONSTANT_NameAndType_info] for above
208:                //  *  [CONSTANT_Methodref_info] for above
209:                //  *  [UTF-8] "floatValue"
210:                //  *  [UTF-8] "()F"
211:                //  *  [CONSTANT_NameAndType_info] for above
212:                //  *  [CONSTANT_Methodref_info] for above
213:                //  *  [UTF-8] "java/lang/Integer"
214:                //  *  [CONSTANT_Class_info] for above
215:                //  *  [UTF-8] "(I)V"
216:                //  *  [CONSTANT_NameAndType_info] for above
217:                //  *  [CONSTANT_Methodref_info] for above
218:                //  *  [UTF-8] "intValue"
219:                //  *  [UTF-8] "()I"
220:                //  *  [CONSTANT_NameAndType_info] for above
221:                //  *  [CONSTANT_Methodref_info] for above
222:                //  *  [UTF-8] "java/lang/Long"
223:                //  *  [CONSTANT_Class_info] for above
224:                //  *  [UTF-8] "(J)V"
225:                //  *  [CONSTANT_NameAndType_info] for above
226:                //  *  [CONSTANT_Methodref_info] for above
227:                //  *  [UTF-8] "longValue"
228:                //  *  [UTF-8] "()J"
229:                //  *  [CONSTANT_NameAndType_info] for above
230:                //  *  [CONSTANT_Methodref_info] for above
231:                //  *  [UTF-8] "java/lang/Short"
232:                //  *  [CONSTANT_Class_info] for above
233:                //  *  [UTF-8] "(S)V"
234:                //  *  [CONSTANT_NameAndType_info] for above
235:                //  *  [CONSTANT_Methodref_info] for above
236:                //  *  [UTF-8] "shortValue"
237:                //  *  [UTF-8] "()S"
238:                //  *  [CONSTANT_NameAndType_info] for above
239:                //  *  [CONSTANT_Methodref_info] for above
240:
241:                short numCPEntries = NUM_BASE_CPOOL_ENTRIES
242:                        + NUM_COMMON_CPOOL_ENTRIES;
243:                boolean usesPrimitives = usesPrimitiveTypes();
244:                if (usesPrimitives) {
245:                    numCPEntries += NUM_BOXING_CPOOL_ENTRIES;
246:                }
247:                if (forSerialization) {
248:                    numCPEntries += NUM_SERIALIZATION_CPOOL_ENTRIES;
249:                }
250:
251:                // Add in variable-length number of entries to be able to describe
252:                // non-primitive parameter types and checked exceptions.
253:                numCPEntries += (short) (2 * numNonPrimitiveParameterTypes());
254:
255:                asm.emitShort(add(numCPEntries, S1));
256:
257:                final String generatedName = generateName(isConstructor,
258:                        forSerialization);
259:                asm.emitConstantPoolUTF8(generatedName);
260:                asm.emitConstantPoolClass(asm.cpi());
261:                this Class = asm.cpi();
262:                if (isConstructor) {
263:                    if (forSerialization) {
264:                        asm
265:                                .emitConstantPoolUTF8("sun/reflect/SerializationConstructorAccessorImpl");
266:                    } else {
267:                        asm
268:                                .emitConstantPoolUTF8("sun/reflect/ConstructorAccessorImpl");
269:                    }
270:                } else {
271:                    asm.emitConstantPoolUTF8("sun/reflect/MethodAccessorImpl");
272:                }
273:                asm.emitConstantPoolClass(asm.cpi());
274:                super Class = asm.cpi();
275:                asm.emitConstantPoolUTF8(getClassName(declaringClass, false));
276:                asm.emitConstantPoolClass(asm.cpi());
277:                targetClass = asm.cpi();
278:                short serializationTargetClassIdx = (short) 0;
279:                if (forSerialization) {
280:                    asm.emitConstantPoolUTF8(getClassName(
281:                            serializationTargetClass, false));
282:                    asm.emitConstantPoolClass(asm.cpi());
283:                    serializationTargetClassIdx = asm.cpi();
284:                }
285:                asm.emitConstantPoolUTF8(name);
286:                asm.emitConstantPoolUTF8(buildInternalSignature());
287:                asm.emitConstantPoolNameAndType(sub(asm.cpi(), S1), asm.cpi());
288:                if (isInterface()) {
289:                    asm.emitConstantPoolInterfaceMethodref(targetClass, asm
290:                            .cpi());
291:                } else {
292:                    if (forSerialization) {
293:                        asm.emitConstantPoolMethodref(
294:                                serializationTargetClassIdx, asm.cpi());
295:                    } else {
296:                        asm.emitConstantPoolMethodref(targetClass, asm.cpi());
297:                    }
298:                }
299:                targetMethodRef = asm.cpi();
300:                if (isConstructor) {
301:                    asm.emitConstantPoolUTF8("newInstance");
302:                } else {
303:                    asm.emitConstantPoolUTF8("invoke");
304:                }
305:                invokeIdx = asm.cpi();
306:                if (isConstructor) {
307:                    asm
308:                            .emitConstantPoolUTF8("([Ljava/lang/Object;)Ljava/lang/Object;");
309:                } else {
310:                    asm
311:                            .emitConstantPoolUTF8("(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;");
312:                }
313:                invokeDescriptorIdx = asm.cpi();
314:
315:                // Output class information for non-primitive parameter types
316:                nonPrimitiveParametersBaseIdx = add(asm.cpi(), S2);
317:                for (int i = 0; i < parameterTypes.length; i++) {
318:                    Class c = parameterTypes[i];
319:                    if (!isPrimitive(c)) {
320:                        asm.emitConstantPoolUTF8(getClassName(c, false));
321:                        asm.emitConstantPoolClass(asm.cpi());
322:                    }
323:                }
324:
325:                // Entries common to FieldAccessor, MethodAccessor and ConstructorAccessor
326:                emitCommonConstantPoolEntries();
327:
328:                // Boxing entries
329:                if (usesPrimitives) {
330:                    emitBoxingContantPoolEntries();
331:                }
332:
333:                if (asm.cpi() != numCPEntries) {
334:                    throw new InternalError("Adjust this code (cpi = "
335:                            + asm.cpi() + ", numCPEntries = " + numCPEntries
336:                            + ")");
337:                }
338:
339:                // Access flags
340:                asm.emitShort(ACC_PUBLIC);
341:
342:                // This class
343:                asm.emitShort(this Class);
344:
345:                // Superclass
346:                asm.emitShort(super Class);
347:
348:                // Interfaces count and interfaces
349:                asm.emitShort(S0);
350:
351:                // Fields count and fields
352:                asm.emitShort(S0);
353:
354:                // Methods count and methods
355:                asm.emitShort(NUM_METHODS);
356:
357:                emitConstructor();
358:                emitInvoke();
359:
360:                // Additional attributes (none)
361:                asm.emitShort(S0);
362:
363:                // Load class
364:                vec.trim();
365:                final byte[] bytes = vec.getData();
366:                // Note: the class loader is the only thing that really matters
367:                // here -- it's important to get the generated code into the
368:                // same namespace as the target class. Since the generated code
369:                // is privileged anyway, the protection domain probably doesn't
370:                // matter.
371:                return (MagicAccessorImpl) AccessController
372:                        .doPrivileged(new PrivilegedAction() {
373:                            public Object run() {
374:                                try {
375:                                    return ClassDefiner.defineClass(
376:                                            generatedName, bytes, 0,
377:                                            bytes.length,
378:                                            declaringClass.getClassLoader())
379:                                            .newInstance();
380:                                } catch (InstantiationException e) {
381:                                    throw (InternalError) new InternalError()
382:                                            .initCause(e);
383:                                } catch (IllegalAccessException e) {
384:                                    throw (InternalError) new InternalError()
385:                                            .initCause(e);
386:                                }
387:                            }
388:                        });
389:            }
390:
391:            /** This emits the code for either invoke() or newInstance() */
392:            private void emitInvoke() {
393:                // NOTE that this code will only handle 65535 parameters since we
394:                // use the sipush instruction to get the array index on the
395:                // operand stack.
396:                if (parameterTypes.length > 65535) {
397:                    throw new InternalError(
398:                            "Can't handle more than 65535 parameters");
399:                }
400:
401:                // Generate code into fresh code buffer
402:                ClassFileAssembler cb = new ClassFileAssembler();
403:                if (isConstructor) {
404:                    // 1 incoming argument
405:                    cb.setMaxLocals(2);
406:                } else {
407:                    // 2 incoming arguments
408:                    cb.setMaxLocals(3);
409:                }
410:
411:                short illegalArgStartPC = 0;
412:
413:                if (isConstructor) {
414:                    // Instantiate target class before continuing
415:                    // new <target class type>
416:                    // dup
417:                    cb.opc_new(targetClass);
418:                    cb.opc_dup();
419:                } else {
420:                    // Setup before iterating down argument list
421:                    if (isPrimitive(returnType)) {
422:                        // new <boxing type for primitive type>
423:                        // dup
424:                        // ... (see below:)
425:                        // invokespecial <constructor for boxing type for primitive type>
426:                        // areturn
427:                        cb.opc_new(indexForPrimitiveType(returnType));
428:                        cb.opc_dup();
429:                    }
430:
431:                    // Get target object on operand stack if necessary.
432:
433:                    // We need to do an explicit null check here; we won't see
434:                    // NullPointerExceptions from the invoke bytecode, since it's
435:                    // covered by an exception handler.
436:                    if (!isStatic()) {
437:                        // aload_1
438:                        // ifnonnull <checkcast label>
439:                        // new <NullPointerException>
440:                        // dup
441:                        // invokespecial <NullPointerException ctor>
442:                        // athrow
443:                        // <checkcast label:>
444:                        // aload_1
445:                        // checkcast <target class's type>
446:                        cb.opc_aload_1();
447:                        Label l = new Label();
448:                        cb.opc_ifnonnull(l);
449:                        cb.opc_new(nullPointerClass);
450:                        cb.opc_dup();
451:                        cb.opc_invokespecial(nullPointerCtorIdx, 0, 0);
452:                        cb.opc_athrow();
453:                        l.bind();
454:                        illegalArgStartPC = cb.getLength();
455:                        cb.opc_aload_1();
456:                        cb.opc_checkcast(targetClass);
457:                    }
458:                }
459:
460:                // Have to check length of incoming array and throw
461:                // IllegalArgumentException if not correct. A concession to the
462:                // JCK (isn't clearly specified in the spec): we allow null in the
463:                // case where the argument list is zero length.
464:                // if no-arg:
465:                //   aload_2 | aload_1 (Method | Constructor)
466:                //   ifnull <success label>
467:                // aload_2 | aload_1
468:                // arraylength
469:                // sipush <num parameter types>
470:                // if_icmpeq <success label>
471:                // new <IllegalArgumentException>
472:                // dup
473:                // invokespecial <IllegalArgumentException ctor>
474:                // athrow
475:                // <success label:>
476:                Label successLabel = new Label();
477:                if (parameterTypes.length == 0) {
478:                    if (isConstructor) {
479:                        cb.opc_aload_1();
480:                    } else {
481:                        cb.opc_aload_2();
482:                    }
483:                    cb.opc_ifnull(successLabel);
484:                }
485:                if (isConstructor) {
486:                    cb.opc_aload_1();
487:                } else {
488:                    cb.opc_aload_2();
489:                }
490:                cb.opc_arraylength();
491:                cb.opc_sipush((short) parameterTypes.length);
492:                cb.opc_if_icmpeq(successLabel);
493:                cb.opc_new(illegalArgumentClass);
494:                cb.opc_dup();
495:                cb.opc_invokespecial(illegalArgumentCtorIdx, 0, 0);
496:                cb.opc_athrow();
497:                successLabel.bind();
498:
499:                // Iterate through incoming actual parameters, ensuring that each
500:                // is compatible with the formal parameter type, and pushing the
501:                // actual on the operand stack (unboxing and widening if necessary).
502:
503:                short paramTypeCPIdx = nonPrimitiveParametersBaseIdx;
504:                Label nextParamLabel = null;
505:                byte count = 1; // both invokeinterface opcode's "count" as well as
506:                // num args of other invoke bytecodes
507:                for (int i = 0; i < parameterTypes.length; i++) {
508:                    Class paramType = parameterTypes[i];
509:                    count += (byte) typeSizeInStackSlots(paramType);
510:                    if (nextParamLabel != null) {
511:                        nextParamLabel.bind();
512:                        nextParamLabel = null;
513:                    }
514:                    // aload_2 | aload_1
515:                    // sipush <index>
516:                    // aaload
517:                    if (isConstructor) {
518:                        cb.opc_aload_1();
519:                    } else {
520:                        cb.opc_aload_2();
521:                    }
522:                    cb.opc_sipush((short) i);
523:                    cb.opc_aaload();
524:                    if (isPrimitive(paramType)) {
525:                        // Unboxing code.
526:                        // Put parameter into temporary local variable
527:                        // astore_3 | astore_2
528:                        if (isConstructor) {
529:                            cb.opc_astore_2();
530:                        } else {
531:                            cb.opc_astore_3();
532:                        }
533:
534:                        // repeat for all possible widening conversions:
535:                        //   aload_3 | aload_2
536:                        //   instanceof <primitive boxing type>
537:                        //   ifeq <next unboxing label>
538:                        //   aload_3 | aload_2
539:                        //   checkcast <primitive boxing type> // Note: this is "redundant",
540:                        //                                     // but necessary for the verifier
541:                        //   invokevirtual <unboxing method>
542:                        //   <widening conversion bytecode, if necessary>
543:                        //   goto <next parameter label>
544:                        // <next unboxing label:> ...
545:                        // last unboxing label:
546:                        //   new <IllegalArgumentException>
547:                        //   dup
548:                        //   invokespecial <IllegalArgumentException ctor>
549:                        //   athrow
550:
551:                        Label l = null; // unboxing label
552:                        nextParamLabel = new Label();
553:
554:                        for (int j = 0; j < primitiveTypes.length; j++) {
555:                            Class c = primitiveTypes[j];
556:                            if (canWidenTo(c, paramType)) {
557:                                if (l != null) {
558:                                    l.bind();
559:                                }
560:                                // Emit checking and unboxing code for this type
561:                                if (isConstructor) {
562:                                    cb.opc_aload_2();
563:                                } else {
564:                                    cb.opc_aload_3();
565:                                }
566:                                cb.opc_instanceof (indexForPrimitiveType(c));
567:                                l = new Label();
568:                                cb.opc_ifeq(l);
569:                                if (isConstructor) {
570:                                    cb.opc_aload_2();
571:                                } else {
572:                                    cb.opc_aload_3();
573:                                }
574:                                cb.opc_checkcast(indexForPrimitiveType(c));
575:                                cb.opc_invokevirtual(
576:                                        unboxingMethodForPrimitiveType(c), 0,
577:                                        typeSizeInStackSlots(c));
578:                                emitWideningBytecodeForPrimitiveConversion(cb,
579:                                        c, paramType);
580:                                cb.opc_goto(nextParamLabel);
581:                            }
582:                        }
583:
584:                        if (l == null) {
585:                            throw new InternalError(
586:                                    "Must have found at least identity conversion");
587:                        }
588:
589:                        // Fell through; given object is null or invalid. According to
590:                        // the spec, we can throw IllegalArgumentException for both of
591:                        // these cases.
592:
593:                        l.bind();
594:                        cb.opc_new(illegalArgumentClass);
595:                        cb.opc_dup();
596:                        cb.opc_invokespecial(illegalArgumentCtorIdx, 0, 0);
597:                        cb.opc_athrow();
598:                    } else {
599:                        // Emit appropriate checkcast
600:                        cb.opc_checkcast(paramTypeCPIdx);
601:                        paramTypeCPIdx = add(paramTypeCPIdx, S2);
602:                        // Fall through to next argument
603:                    }
604:                }
605:                // Bind last goto if present
606:                if (nextParamLabel != null) {
607:                    nextParamLabel.bind();
608:                }
609:
610:                short invokeStartPC = cb.getLength();
611:
612:                // OK, ready to perform the invocation.
613:                if (isConstructor) {
614:                    cb.opc_invokespecial(targetMethodRef, count, 0);
615:                } else {
616:                    if (isStatic()) {
617:                        cb.opc_invokestatic(targetMethodRef, count,
618:                                typeSizeInStackSlots(returnType));
619:                    } else {
620:                        if (isInterface()) {
621:                            cb.opc_invokeinterface(targetMethodRef, count,
622:                                    count, typeSizeInStackSlots(returnType));
623:                        } else {
624:                            cb.opc_invokevirtual(targetMethodRef, count,
625:                                    typeSizeInStackSlots(returnType));
626:                        }
627:                    }
628:                }
629:
630:                short invokeEndPC = cb.getLength();
631:
632:                if (!isConstructor) {
633:                    // Box return value if necessary
634:                    if (isPrimitive(returnType)) {
635:                        cb.opc_invokespecial(
636:                                ctorIndexForPrimitiveType(returnType),
637:                                typeSizeInStackSlots(returnType), 0);
638:                    } else if (returnType == Void.TYPE) {
639:                        cb.opc_aconst_null();
640:                    }
641:                }
642:                cb.opc_areturn();
643:
644:                // We generate two exception handlers; one which is responsible
645:                // for catching ClassCastException and NullPointerException and
646:                // throwing IllegalArgumentException, and the other which catches
647:                // all java/lang/Throwable objects thrown from the target method
648:                // and wraps them in InvocationTargetExceptions.
649:
650:                short classCastHandler = cb.getLength();
651:
652:                // ClassCast, etc. exception handler
653:                cb.setStack(1);
654:                cb.opc_invokespecial(toStringIdx, 0, 1);
655:                cb.opc_new(illegalArgumentClass);
656:                cb.opc_dup_x1();
657:                cb.opc_swap();
658:                cb.opc_invokespecial(illegalArgumentStringCtorIdx, 1, 0);
659:                cb.opc_athrow();
660:
661:                short invocationTargetHandler = cb.getLength();
662:
663:                // InvocationTargetException exception handler
664:                cb.setStack(1);
665:                cb.opc_new(invocationTargetClass);
666:                cb.opc_dup_x1();
667:                cb.opc_swap();
668:                cb.opc_invokespecial(invocationTargetCtorIdx, 1, 0);
669:                cb.opc_athrow();
670:
671:                // Generate exception table. We cover the entire code sequence
672:                // with an exception handler which catches ClassCastException and
673:                // converts it into an IllegalArgumentException.
674:
675:                ClassFileAssembler exc = new ClassFileAssembler();
676:
677:                exc.emitShort(illegalArgStartPC); // start PC
678:                exc.emitShort(invokeStartPC); // end PC
679:                exc.emitShort(classCastHandler); // handler PC
680:                exc.emitShort(classCastClass); // catch type
681:
682:                exc.emitShort(illegalArgStartPC); // start PC
683:                exc.emitShort(invokeStartPC); // end PC
684:                exc.emitShort(classCastHandler); // handler PC
685:                exc.emitShort(nullPointerClass); // catch type
686:
687:                exc.emitShort(invokeStartPC); // start PC
688:                exc.emitShort(invokeEndPC); // end PC
689:                exc.emitShort(invocationTargetHandler); // handler PC
690:                exc.emitShort(throwableClass); // catch type
691:
692:                emitMethod(invokeIdx, cb.getMaxLocals(), cb, exc,
693:                        new short[] { invocationTargetClass });
694:            }
695:
696:            private boolean usesPrimitiveTypes() {
697:                // We need to emit boxing/unboxing constant pool information if
698:                // the method takes a primitive type for any of its parameters or
699:                // returns a primitive value (except void)
700:                if (returnType.isPrimitive()) {
701:                    return true;
702:                }
703:                for (int i = 0; i < parameterTypes.length; i++) {
704:                    if (parameterTypes[i].isPrimitive()) {
705:                        return true;
706:                    }
707:                }
708:                return false;
709:            }
710:
711:            private int numNonPrimitiveParameterTypes() {
712:                int num = 0;
713:                for (int i = 0; i < parameterTypes.length; i++) {
714:                    if (!parameterTypes[i].isPrimitive()) {
715:                        ++num;
716:                    }
717:                }
718:                return num;
719:            }
720:
721:            private boolean isInterface() {
722:                return declaringClass.isInterface();
723:            }
724:
725:            private String buildInternalSignature() {
726:                StringBuffer buf = new StringBuffer();
727:                buf.append("(");
728:                for (int i = 0; i < parameterTypes.length; i++) {
729:                    buf.append(getClassName(parameterTypes[i], true));
730:                }
731:                buf.append(")");
732:                buf.append(getClassName(returnType, true));
733:                return buf.toString();
734:            }
735:
736:            private static synchronized String generateName(
737:                    boolean isConstructor, boolean forSerialization) {
738:                if (isConstructor) {
739:                    if (forSerialization) {
740:                        int num = ++serializationConstructorSymnum;
741:                        return "sun/reflect/GeneratedSerializationConstructorAccessor"
742:                                + num;
743:                    } else {
744:                        int num = ++constructorSymnum;
745:                        return "sun/reflect/GeneratedConstructorAccessor" + num;
746:                    }
747:                } else {
748:                    int num = ++methodSymnum;
749:                    return "sun/reflect/GeneratedMethodAccessor" + num;
750:                }
751:            }
752:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.