Source Code Cross Referenced for NativePeer.java in  » Code-Analyzer » javapathfinder » gov » nasa » jpf » jvm » 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 » Code Analyzer » javapathfinder » gov.nasa.jpf.jvm 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        //
002:        // Copyright (C) 2005 United States Government as represented by the
003:        // Administrator of the National Aeronautics and Space Administration
004:        // (NASA).  All Rights Reserved.
005:        // 
006:        // This software is distributed under the NASA Open Source Agreement
007:        // (NOSA), version 1.3.  The NOSA has been approved by the Open Source
008:        // Initiative.  See the file NOSA-1.3-JPF at the top of the distribution
009:        // directory tree for the complete NOSA document.
010:        // 
011:        // THE SUBJECT SOFTWARE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY OF ANY
012:        // KIND, EITHER EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING, BUT NOT
013:        // LIMITED TO, ANY WARRANTY THAT THE SUBJECT SOFTWARE WILL CONFORM TO
014:        // SPECIFICATIONS, ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR
015:        // A PARTICULAR PURPOSE, OR FREEDOM FROM INFRINGEMENT, ANY WARRANTY THAT
016:        // THE SUBJECT SOFTWARE WILL BE ERROR FREE, OR ANY WARRANTY THAT
017:        // DOCUMENTATION, IF PROVIDED, WILL CONFORM TO THE SUBJECT SOFTWARE.
018:        //
019:        package gov.nasa.jpf.jvm;
020:
021:        import gov.nasa.jpf.Config;
022:        import gov.nasa.jpf.JPFException;
023:        import gov.nasa.jpf.jvm.bytecode.Instruction;
024:        import gov.nasa.jpf.util.Debug;
025:
026:        import java.lang.reflect.*;
027:
028:        import java.util.HashMap;
029:        import java.util.Map;
030:
031:        /**
032:         * native peer classes are part of MJI and contain the code that is
033:         * executed by the host VM (i.e. outside the state-tracked JPF JVM). Each
034:         * class executed by JPF that has native mehods must have a native peer class
035:         * (which is looked up and associated at class loadtime)
036:         */
037:        public class NativePeer {
038:            static ClassLoader loader;
039:            static HashMap peers;
040:            static final String COND_EXEC_PREFIX = "$isExecutable_";
041:            static final String COND_DETERM_PREFIX = "$isDeterministic_";
042:            static final int MAX = 6;
043:            static Object[][] argCache;
044:
045:            ClassInfo ci;
046:            Class peerClass;
047:            HashMap methods;
048:
049:            public static void init(Config config) {
050:                // we don't do fancy things yet, but at some point, we might
051:                // want to use a specific ClassLoader - just to make sure the
052:                // peer classes are not colliding with other stuff
053:                loader = ClassLoader.getSystemClassLoader();
054:                peers = new HashMap();
055:
056:                argCache = new Object[MAX][];
057:
058:                for (int i = 0; i < MAX; i++) {
059:                    argCache[i] = new Object[i];
060:                }
061:            }
062:
063:            NativePeer() {
064:                // just here for our derived classes
065:            }
066:
067:            NativePeer(Class peerClass, ClassInfo ci) {
068:                initialize(peerClass, ci, true);
069:            }
070:
071:            /**
072:             * this becomes the factory method to load either a plain (slow)
073:             * reflection-based peer (a NativePeer object), or some speed optimized
074:             * derived class object.
075:             * Watch out - this gets called before the ClassInfo is fully initialized
076:             * (we shouldn't rely on more than just its name here)
077:             */
078:            static NativePeer getNativePeer(ClassInfo ci) {
079:                String clsName = ci.getName();
080:                NativePeer peer = (NativePeer) peers.get(clsName);
081:                Class peerCls = null;
082:                String pcn = null;
083:
084:                if (peer == null) {
085:                    // <2do> - we really should come up with our own classloader
086:                    // so that we don't have to rely on ClassNotFoundException for
087:                    // the lookup
088:                    try {
089:                        pcn = getSystemPeerClassName(clsName);
090:                        peerCls = loader.loadClass(pcn);
091:                    } catch (Throwable x) {
092:                        try {
093:                            pcn = getUserPeerClassName(clsName);
094:                            peerCls = loader.loadClass(pcn);
095:                        } catch (Throwable xx) {
096:                            try {
097:                                pcn = getGlobalPeerClassName(clsName);
098:                                peerCls = loader.loadClass(pcn);
099:                            } catch (Throwable xxx) {
100:                                // we could throw an exception in case there are native methods
101:                                // in ci, but a JVM would only hickup with UnsatisfiedLinkError
102:                                // if such a method is actually called
103:                            }
104:                        }
105:                    }
106:
107:                    if (peerCls != null) {
108:                        try {
109:                            String dcn = getPeerDispatcherClassName(peerCls
110:                                    .getName());
111:                            Class dispatcherClass = loader.loadClass(dcn);
112:
113:                            Debug.print(Debug.DEBUG, "load peer dispatcher: ");
114:                            Debug.println(Debug.DEBUG, dcn);
115:
116:                            peer = (NativePeer) dispatcherClass.newInstance();
117:                            peer.initialize(peerCls, ci, false);
118:                        } catch (Throwable xxxx) {
119:                            if (!(xxxx instanceof  ClassNotFoundException)) {
120:                                // maybe we should bail here
121:                                System.err.println("error loading dispatcher: "
122:                                        + xxxx);
123:                            }
124:
125:                            Debug.print(Debug.DEBUG, "load peer: ");
126:                            Debug.println(Debug.DEBUG, pcn);
127:
128:                            peer = new NativePeer(peerCls, ci);
129:                        }
130:
131:                        if (peer != null) {
132:                            peers.put(clsName, peer);
133:                        }
134:                    }
135:                }
136:
137:                return peer;
138:            }
139:
140:            static String getPeerDispatcherClassName(String clsName) {
141:                return (clsName + '$');
142:            }
143:
144:            /**
145:             * "system peer" classes reside in gov...jvm, i.e. they can do
146:             * whatever JPF internal stuff they want to
147:             */
148:            static String getSystemPeerClassName(String clsName) {
149:                // we still need the "JPF_" prefix in case of native methods w/o packages
150:                return "gov.nasa.jpf.jvm.JPF_" + clsName.replace('.', '_');
151:            }
152:
153:            /**
154:             * look up peer classes in same package like the model class. This is kind
155:             * of misleading since the model only gets seen by JPF, and the peer only
156:             * by the host VM, but it makes it easier to distribute if this is an
157:             * application specific combo. Otherwise the package of the native peer should
158:             * be chosen so that it can access the host VM classes it needs
159:             */
160:            static String getUserPeerClassName(String clsName) {
161:                int i = clsName.lastIndexOf('.');
162:                String pkg = clsName.substring(0, i + 1);
163:
164:                return (pkg + "JPF_" + clsName.replace('.', '_'));
165:            }
166:
167:            /**
168:             * lookup the native peer as a global (i.e. no package) class. This is still
169:             * safe because the peer classname is fully qualified (has the model
170:             * package in it)
171:             * "user peer" classes are confined to what MJIEnv allows them to do
172:             * (no package required, since the target class package is mangled into
173:             * the name itself)
174:             */
175:            static String getGlobalPeerClassName(String clsName) {
176:                return "JPF_" + clsName.replace('.', '_');
177:            }
178:
179:            boolean isMethodCondDeterministic(ThreadInfo ti, MethodInfo mi) {
180:                Boolean ret = Boolean.FALSE;
181:                Object[] args = null;
182:                Method mth;
183:                MJIEnv env = ti.getMJIEnv();
184:
185:                env.setCallEnvironment(mi);
186:
187:                if ((mth = getDetermCondMethod(mi)) == null) {
188:                    // we should never get here, since existence of this method
189:                    // is used to determine the attribute value
190:                    throw new JPFException("no isDeterministic() condition: "
191:                            + mi.getName());
192:                }
193:
194:                try {
195:                    args = getArguments(env, ti, mi, mth);
196:                    ret = (Boolean) mth.invoke(peerClass, args);
197:
198:                    // leave everything on the stack
199:                } catch (Throwable x) {
200:                    // <2do> - BAD, should behave like executeMethod
201:                    x.printStackTrace();
202:                }
203:
204:                return ret.booleanValue();
205:            }
206:
207:            boolean isMethodCondExecutable(ThreadInfo ti, MethodInfo mi) {
208:                Boolean ret = Boolean.FALSE;
209:                Object[] args = null;
210:                Method mth;
211:                MJIEnv env = ti.getMJIEnv();
212:
213:                env.setCallEnvironment(mi);
214:
215:                if ((mth = getExecCondMethod(mi)) == null) {
216:                    // we should never get here, since existence of this method
217:                    // is used to determine the attribute value
218:                    throw new JPFException("no isExecutable() condition: "
219:                            + mi.getName());
220:                }
221:
222:                try {
223:                    args = getArguments(env, ti, mi, mth);
224:                    ret = (Boolean) mth.invoke(peerClass, args);
225:
226:                    // leave everything on the stack
227:                } catch (Throwable x) {
228:                    // <2do> - BAD, should behave like executeMethod
229:                    x.printStackTrace();
230:                }
231:
232:                return ret.booleanValue();
233:            }
234:
235:            boolean isMethodDeterministic(Method m) {
236:                // Eeeek - we do the evil C++ thing here - we borrow a method modifier
237:                // for the purpose of marking non-deterministic methods. 'final' seems
238:                // to be the best bad choice (given that all methods are static).
239:                // Note that we have to check this from the ClassInfo init (i.e. lookup
240:                // via MethodInfo), because reverse lookup (Method->MethodInfo) is
241:                // difficult (we don't have the exact return type info, which is
242:                // part of the signature)
243:                return ((m.getModifiers() & Modifier.FINAL) == 0);
244:            }
245:
246:            Instruction executeMethod(ThreadInfo ti, MethodInfo mi) {
247:                Object ret = null;
248:                Object[] args = null;
249:                Method mth;
250:                String exception;
251:                MJIEnv env = ti.getMJIEnv();
252:                ElementInfo ei = null;
253:
254:                env.setCallEnvironment(mi);
255:
256:                if ((mth = getMethod(mi)) == null) {
257:                    return ti.createAndThrowException(
258:                            "java.lang.UnsatisfiedLinkError",
259:                            "cannot find native " + ci.getName() + '.'
260:                                    + mi.getName());
261:                }
262:
263:                try {
264:                    args = getArguments(env, ti, mi, mth);
265:
266:                    // we have to lock here in case a native method does sync stuff, so that
267:                    // we don't run into IllegalMonitorStateExceptions
268:                    if (mi.isSynchronized()) {
269:                        ei = env.getElementInfo(((Integer) args[1]).intValue());
270:                        ei.lock(ti);
271:                    }
272:
273:                    ret = mth.invoke(peerClass, args);
274:
275:                    // these are our non-standard returns
276:                    if ((exception = env.getException()) != null) {
277:                        String details = env.getExceptionDetails();
278:
279:                        // even though we should prefer throwing normal exceptions,
280:                        // sometimes it might be better/required to explicitly throw
281:                        // something that's not wrapped into a InvocationTargetException
282:                        // (e.g. InterruptedException), which is why there still is a
283:                        // MJIEnv.throwException()
284:                        return ti.createAndThrowException(exception, details);
285:                    }
286:
287:                    if (env.getRepeat()) {
288:                        // call it again
289:                        return ti.getPC();
290:                    }
291:
292:                    // Ok, we did 'return', clean up the stack
293:                    // note that we don't have a stack frame for this
294:                    // sucker (for state and speed sake), so we just pop the arguments here
295:                    ti.removeArguments(mi);
296:
297:                    pushReturnValue(ti, mi, ret);
298:                } catch (IllegalArgumentException iax) {
299:                    System.out.println(iax);
300:                    return ti.createAndThrowException(
301:                            "java.lang.IllegalArgumentException", "calling "
302:                                    + ci.getName() + '.' + mi.getName());
303:                } catch (IllegalAccessException ilax) {
304:                    return ti.createAndThrowException(
305:                            "java.lang.IllegalAccessException", "calling "
306:                                    + ci.getName() + '.' + mi.getName());
307:                } catch (InvocationTargetException itx) {
308:                    // this will catch all exceptions thrown by the native method execution
309:                    // (automatically transformed by java.lang.reflect.Method.invoke())
310:                    return ti.createAndThrowException(
311:                            "java.lang.reflect.InvocationTargetException",
312:                            "in " + ci.getName() + '.' + mi.getName() + " : "
313:                                    + itx.getCause());
314:                } finally {
315:                    // no matter what - if we grabbed the lock, we have to release it
316:                    // but the native method body might actually have given up the lock, so
317:                    // check first
318:                    if (mi.isSynchronized() && ei.isLocked()) {
319:                        ei.unlock(ti);
320:                    }
321:
322:                    // bad native methods might keep references around
323:                    env.clearCallEnvironment();
324:                }
325:
326:                Instruction pc = ti.getPC();
327:
328:                // <2do> - in case of the current System.exit() implementation, all the
329:                // stackframes are gone and there is no pc anymore. Until we use a more
330:                // explicit end condition, we have to check for this here (the return value
331:                // should not matter)
332:                if (pc == null) {
333:                    return null;
334:                }
335:
336:                // there is no RETURN for a native method, so we have to advance explicitly
337:                return pc.getNext();
338:            }
339:
340:            void initialize(Class peerClass, ClassInfo ci, boolean cacheMethods) {
341:                if ((this .ci != null) || (this .peerClass != null)) {
342:                    throw new RuntimeException(
343:                            "cannot re-initialize NativePeer: "
344:                                    + peerClass.getName());
345:                }
346:
347:                this .ci = ci;
348:                this .peerClass = peerClass;
349:
350:                loadMethods(cacheMethods);
351:            }
352:
353:            private static boolean isMJICandidate(Method mth) {
354:                // only the public static ones are supposed to be native method impls
355:                return ((mth.getModifiers() & (Modifier.PUBLIC | Modifier.STATIC)) == (Modifier.PUBLIC | Modifier.STATIC));
356:            }
357:
358:            private Object[] getArgArray(int n) {
359:                // JPF BC execution is not multi-threaded, and argument conversion
360:                // should NOT happen recursively (hint hint), so we are rather primitive here.
361:                // (actually, argument array can happen recursive, but since they are
362:                // only used to pass the values, we just care up to the invoke() call)
363:                if (n < MAX) {
364:                    return argCache[n];
365:                } else {
366:                    return new Object[n];
367:                }
368:            }
369:
370:            /**
371:             * Get and convert the native method parameters off the ThreadInfo stack.
372:             * Use the MethodInfo parameter type info for this (not the reflect.Method
373:             * type array), or otherwise we won't have any type check
374:             */
375:            private Object[] getArguments(MJIEnv env, ThreadInfo ti,
376:                    MethodInfo mi, Method mth) {
377:                int nArgs = mi.getNumberOfArguments();
378:                Object[] a = getArgArray(nArgs + 2);
379:                byte[] argTypes = mi.getArgumentTypes();
380:                int stackOffset;
381:                int i;
382:                int j;
383:                int k;
384:                int ival;
385:                long lval;
386:
387:                for (i = 0, stackOffset = 0, j = nArgs + 1, k = nArgs - 1; i < nArgs; i++, j--, k--) {
388:                    switch (argTypes[k]) {
389:                    case Types.T_BOOLEAN:
390:                        ival = ti.peek(stackOffset);
391:                        a[j] = new Boolean(Types.intToBoolean(ival));
392:
393:                        break;
394:
395:                    case Types.T_BYTE:
396:                        ival = ti.peek(stackOffset);
397:                        a[j] = new Byte((byte) ival);
398:
399:                        break;
400:
401:                    case Types.T_CHAR:
402:                        ival = ti.peek(stackOffset);
403:                        a[j] = new Character((char) ival);
404:
405:                        break;
406:
407:                    case Types.T_SHORT:
408:                        ival = ti.peek(stackOffset);
409:                        a[j] = new Short((short) ival);
410:
411:                        break;
412:
413:                    case Types.T_INT:
414:                        ival = ti.peek(stackOffset);
415:                        a[j] = new Integer(ival);
416:
417:                        break;
418:
419:                    case Types.T_LONG:
420:                        lval = ti.longPeek(stackOffset);
421:                        stackOffset++; // 2 stack words
422:                        a[j] = new Long(lval);
423:
424:                        break;
425:
426:                    case Types.T_FLOAT:
427:                        ival = ti.peek(stackOffset);
428:                        a[j] = new Float(Types.intToFloat(ival));
429:
430:                        break;
431:
432:                    case Types.T_DOUBLE:
433:                        lval = ti.longPeek(stackOffset);
434:                        stackOffset++; // 2 stack words
435:                        a[j] = new Double(Types.longToDouble(lval));
436:
437:                        break;
438:
439:                    default:
440:                        ival = ti.peek(stackOffset);
441:                        a[j] = new Integer(ival);
442:                    }
443:
444:                    stackOffset++;
445:                }
446:
447:                if (mi.isStatic()) {
448:                    a[1] = new Integer(ci.getClassObjectRef());
449:                } else {
450:                    a[1] = new Integer(ti.getCalleeThis(mi));
451:                }
452:
453:                a[0] = env;
454:
455:                return a;
456:            }
457:
458:            private Method getDetermCondMethod(MethodInfo mi) {
459:                return getMethod(COND_DETERM_PREFIX, mi);
460:            }
461:
462:            private Method getExecCondMethod(MethodInfo mi) {
463:                return getMethod(COND_EXEC_PREFIX, mi);
464:            }
465:
466:            private void setMJIAttributes(MethodInfo mi,
467:                    boolean isDeterministic, boolean isCondDeterministic,
468:                    boolean isCondExecutable) {
469:                mi.setMJI(true);
470:
471:                // don't overwrite explicitly set attributes with defaults
472:                if (!isDeterministic) {
473:                    mi.setDeterministic(isDeterministic);
474:                }
475:
476:                if (isCondDeterministic) {
477:                    mi.setCondDeterministic(isCondDeterministic);
478:                }
479:
480:                if (isCondExecutable) {
481:                    mi.setCondExecutable(isCondExecutable);
482:                }
483:            }
484:
485:            private Method getMethod(MethodInfo mi) {
486:                return getMethod(null, mi);
487:            }
488:
489:            private Method getMethod(String prefix, MethodInfo mi) {
490:                String name = mi.getUniqueName();
491:
492:                if (prefix != null) {
493:                    name = prefix + name;
494:                }
495:
496:                return (Method) methods.get(name);
497:            }
498:
499:            /**
500:             * look at all public static methods in the peer and set their
501:             * corresponding model class MethodInfo attributes
502:             * <2do> pcm - this is too long, break it down
503:             */
504:            private void loadMethods(boolean cacheMethods) {
505:                Method[] m = peerClass.getDeclaredMethods();
506:                methods = new HashMap(m.length);
507:
508:                Map methodInfos = ci.getDeclaredMethods();
509:                MethodInfo[] mis = null;
510:
511:                for (int i = 0; i < m.length; i++) {
512:                    boolean isDeterministic = true;
513:                    boolean isCondDeterministic = false;
514:                    boolean isCondExecutable = false;
515:                    String prefix = "";
516:                    Method mth = m[i];
517:
518:                    if (isMJICandidate(mth)) {
519:                        // Note that we can't mangle the name automatically, since we loose the
520:                        // object type info (all mapped to int). This has to be handled
521:                        // the same way like with overloaded JNI methods - you have to
522:                        // mangle them manually
523:                        String mn = mth.getName();
524:
525:                        // JNI doesn't allow <clinit> or <init> to be native, but MJI does
526:                        // (you should know what you are doing before you use that, really)
527:                        if (mn.equals("$clinit")) {
528:                            mn = "<clinit>";
529:                        } else if (mn.startsWith("$init")) {
530:                            mn = "<init>" + mn.substring(5);
531:                        }
532:
533:                        // check if this is just a attribute method
534:                        if (mn.startsWith(COND_DETERM_PREFIX)) {
535:                            prefix = COND_DETERM_PREFIX;
536:                            mn = mn.substring(17);
537:                            isCondDeterministic = true;
538:                        } else if (mn.startsWith(COND_EXEC_PREFIX)) {
539:                            prefix = COND_EXEC_PREFIX;
540:                            mn = mn.substring(14);
541:                            isCondExecutable = true;
542:                        } else { // no, it's the real thing
543:                            isDeterministic = isMethodDeterministic(mth);
544:                        }
545:
546:                        String mname = Types.getJNIMethodName(mn);
547:                        String argSig = Types.getJNIArgSignature(mn);
548:
549:                        if (argSig != null) {
550:                            mname += argSig;
551:                        }
552:
553:                        // now try to find a corresponding MethodInfo object and mark it
554:                        // as 'peer-ed'
555:                        // <2do> in case of <clinit>, it wouldn't be strictly required to
556:                        // have a MethodInfo upfront (we could create it). Might be handy
557:                        // for classes where we intercept just a few methods, but need
558:                        // to init before
559:                        MethodInfo mi = (MethodInfo) methodInfos.get(mname);
560:
561:                        if ((mi == null) && (argSig == null)) {
562:                            // nothing found, we have to do it the hard way - check if there is
563:                            // a single method with this name (still unsafe, but JNI behavior)
564:                            // Note there's no point in doing that if we do have a signature
565:                            if (mis == null) { // cache it for subsequent lookup
566:                                mis = new MethodInfo[methodInfos.size()];
567:                                methodInfos.values().toArray(mis);
568:                            }
569:
570:                            mi = searchMethod(mname, mis);
571:                        }
572:
573:                        if (mi != null) {
574:                            Debug.print(Debug.DEBUG, "  load MJI method: ");
575:                            Debug.print(Debug.DEBUG, prefix);
576:                            Debug.println(Debug.DEBUG, mname);
577:
578:                            setMJIAttributes(mi, isDeterministic,
579:                                    isCondDeterministic, isCondExecutable);
580:
581:                            if (cacheMethods) {
582:                                if (isCondDeterministic || isCondExecutable) {
583:                                    // register the condition method
584:                                    methods.put(prefix + mi.getUniqueName(),
585:                                            mth);
586:                                } else {
587:                                    // register the real thing
588:                                    methods.put(mi.getUniqueName(), mth); // no use to store unless it can be called!
589:                                }
590:                            } else {
591:                                // otherwise we are just interested in setting the MethodInfo attributes
592:                            }
593:                        } else {
594:                            // issue a warning if we have a NativePeer native method w/o a corresponding
595:                            // method in the model class (this might happen due to compiler optimizations
596:                            // silently skipping empty methods)
597:                            Debug.println(Debug.WARNING,
598:                                    "orphant NativePeer method: "
599:                                            + ci.getName() + '.' + mn);
600:                        }
601:                    }
602:                }
603:            }
604:
605:            private static MethodInfo searchMethod(String mname,
606:                    MethodInfo[] methods) {
607:                for (int j = 0; j < methods.length; j++) {
608:                    if (methods[j].getName().equals(mname)) {
609:                        // if this is actually a overloaded method, and the first one
610:                        // isn't the right choice, we will get a IllegalArgumentException
611:                        // later-on. Hence no need to spend more effort here - but
612:                        // could be optional.
613:                        // <2do> - actually, we should try harder and check if there's
614:                        // only one native candidate if we have a ambiguity (again JNI analogy)
615:                        return methods[j];
616:                    }
617:                }
618:
619:                return null;
620:            }
621:
622:            private void pushReturnValue(ThreadInfo ti, MethodInfo mi,
623:                    Object ret) {
624:                int ival;
625:                long lval;
626:
627:                // in case of a return type mismatch, we get a ClassCastException, which
628:                // is handled in executeMethod() and reported as a InvocationTargetException
629:                // (not completely accurate, but we rather go with safety)
630:                if (ret != null) {
631:                    switch (mi.getReturnType()) {
632:                    case Types.T_BOOLEAN:
633:                        ival = Types.booleanToInt(((Boolean) ret)
634:                                .booleanValue());
635:                        ti.push(ival, false);
636:
637:                        break;
638:
639:                    case Types.T_BYTE:
640:                        ti.push(((Byte) ret).byteValue(), false);
641:
642:                        break;
643:
644:                    case Types.T_CHAR:
645:                        ti.push(((Character) ret).charValue(), false);
646:
647:                        break;
648:
649:                    case Types.T_SHORT:
650:                        ti.push(((Short) ret).shortValue(), false);
651:
652:                        break;
653:
654:                    case Types.T_INT:
655:                        ti.push(((Integer) ret).intValue(), false);
656:
657:                        break;
658:
659:                    case Types.T_LONG:
660:                        ti.longPush(((Long) ret).longValue());
661:
662:                        break;
663:
664:                    case Types.T_FLOAT:
665:                        ival = Types.floatToInt(((Float) ret).floatValue());
666:                        ti.push(ival, false);
667:
668:                        break;
669:
670:                    case Types.T_DOUBLE:
671:                        lval = Types.doubleToLong(((Double) ret).doubleValue());
672:                        ti.longPush(lval);
673:
674:                        break;
675:
676:                    default:
677:
678:                        // everything else is supposed to be a reference
679:                        ti.push(((Integer) ret).intValue(), true);
680:                    }
681:                }
682:            }
683:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.