1f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
2f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Copyright (C) 2008 The Android Open Source Project
3f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
4f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
5f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * you may not use this file except in compliance with the License.
6f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * You may obtain a copy of the License at
7f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
8f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
9f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
10f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
11f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
12f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * See the License for the specific language governing permissions and
14f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * limitations under the License.
15f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1659b6177e2fa9c9f1f16d7eff57e481f5282afbdaAndy McFadden
17f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
18f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Dalvik implementation of JNI interfaces.
19f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
20f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include "Dalvik.h"
21f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include "JniInternal.h"
22483eedc3f30dcaf7ddb2f1b928db8608d9d38ffeElliott Hughes#include "Misc.h"
2389383030aca8f77aeab73540404ba332ce5ac035Elliott Hughes#include "ScopedPthreadMutexLock.h"
24a5f3ed80b3b058b006ee2b09915d1400cebd0442Elliott Hughes#include "UniquePtr.h"
25f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
26f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <stdlib.h>
27f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <stdarg.h>
28f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <limits.h>
29f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
30f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
31f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectNative methods and interaction with the GC
32f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
33f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectAll JNI methods must start by changing their thread status to
34f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectTHREAD_RUNNING, and finish by changing it back to THREAD_NATIVE before
35f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectreturning to native code.  The switch to "running" triggers a thread
36f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectsuspension check.
37f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
38f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectWith a rudimentary GC we should be able to skip the status change for
39f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectsimple functions, e.g.  IsSameObject, GetJavaVM, GetStringLength, maybe
40f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projecteven access to fields with primitive types.  Our options are more limited
410647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hugheswith a compacting GC.
42f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
43f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectFor performance reasons we do as little error-checking as possible here.
44f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectFor example, we don't check to make sure the correct type of Object is
45f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectpassed in when setting a field, and we don't prevent you from storing
46f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectnew values in a "final" field.  Such things are best handled in the
47f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project"check" version.  For actions that are common, dangerous, and must be
48f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectchecked at runtime, such as array bounds checks, we do the tests here.
49f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
50f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
51f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectGeneral notes on local/global reference tracking
52f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
530083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFaddenJNI provides explicit control over natively-held references that the GC
54f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectneeds to know about.  These can be local, in which case they're released
550083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFaddenwhen the native method returns into the VM, or global, which are held
56d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFaddenuntil explicitly released.  (There are also weak-global references,
57d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFaddenwhich have the lifespan and visibility of global references, but the
58d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFaddenobject they refer to may be collected.)
590083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden
600083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFaddenThe references can be created with explicit JNI NewLocalRef / NewGlobalRef
610083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFaddencalls.  The former is very unusual, the latter is reasonably common
620083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden(e.g. for caching references to class objects).
630083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden
640083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFaddenLocal references are most often created as a side-effect of JNI functions.
650083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFaddenFor example, the AllocObject/NewObject functions must create local
660083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFaddenreferences to the objects returned, because nothing else in the GC root
670083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFaddenset has a reference to the new objects.
68f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
69f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectThe most common mode of operation is for a method to create zero or
70f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectmore local references and return.  Explicit "local delete" operations
71f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectare expected to be exceedingly rare, except when walking through an
72f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectobject array, and the Push/PopLocalFrame calls are expected to be used
73f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectinfrequently.  For efficient operation, we want to add new local refs
74f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectwith a simple store/increment operation; to avoid infinite growth in
75f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectpathological situations, we need to reclaim the space used by deleted
76f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectentries.
77f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
78d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFaddenIf we just want to maintain a list for the GC root set, we can use an
79d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFaddenexpanding append-only array that compacts when objects are deleted.
80d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFaddenIn typical situations, e.g. running through an array of objects, we will
81d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFaddenbe deleting one of the most recently added entries, so we can minimize
82d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFaddenthe number of elements moved (or avoid having to move any).
83d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden
84d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFaddenIf we want to conceal the pointer values from native code, which is
85d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFaddennecessary to allow the GC to move JNI-referenced objects around, then we
86d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFaddenhave to use a more complicated indirection mechanism.
87f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
88f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectThe spec says, "Local references are only valid in the thread in which
89f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectthey are created.  The native code must not pass local references from
900083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFaddenone thread to another."
91f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
92f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
93d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFaddenPinned objects
94d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden
95d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFaddenFor some large chunks of data, notably primitive arrays and String data,
96d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFaddenJNI allows the VM to choose whether it wants to pin the array object or
97d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFaddenmake a copy.  We currently pin the memory for better execution performance.
98d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden
99d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFaddenTODO: we're using simple root set references to pin primitive array data,
100d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFaddenbecause they have the property we need (i.e. the pointer we return is
101d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFaddenguaranteed valid until we explicitly release it).  However, if we have a
102d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFaddencompacting GC and don't want to pin all memory held by all global refs,
103d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFaddenwe need to treat these differently.
104d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden
105d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden
106f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectGlobal reference tracking
107f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
108f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectThere should be a small "active" set centered around the most-recently
109d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFaddenadded items.
110f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
111d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFaddenBecause it's global, access to it has to be synchronized.  Additions and
112d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFaddenremovals require grabbing a mutex.  If the table serves as an indirection
113d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFaddenmechanism (i.e. it's not just a list for the benefit of the garbage
114d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFaddencollector), reference lookups may also require grabbing a mutex.
115f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
116f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectThe JNI spec does not define any sort of limit, so the list must be able
117d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFaddento expand to a reasonable size.  It may be useful to log significant
118d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFaddenincreases in usage to help identify resource leaks.
119d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden
120f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
121d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFaddenWeak-global reference tracking
122d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden
123d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden[TBD]
124f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
125f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
126f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectLocal reference tracking
127f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
12888eaaaa90aa4354003de0937b7aebe03bdbce6ebElliott HughesEach Thread/JNIEnv points to an IndirectRefTable.
129f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
130f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectWe implement Push/PopLocalFrame with actual stack frames.  Before a JNI
131f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectframe gets popped, we set "nextEntry" to the "top" pointer of the current
132f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectframe, effectively releasing the references.
133f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
13488eaaaa90aa4354003de0937b7aebe03bdbce6ebElliott HughesThe GC will scan all references in the table.
135f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
136f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project*/
137f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
13885e8913705f23a5e799690134746219f64498f29Elliott Hughesstatic void ReportJniError() {
13985e8913705f23a5e799690134746219f64498f29Elliott Hughes    dvmDumpThread(dvmThreadSelf(), false);
14085e8913705f23a5e799690134746219f64498f29Elliott Hughes    dvmAbort();
14185e8913705f23a5e799690134746219f64498f29Elliott Hughes}
14285e8913705f23a5e799690134746219f64498f29Elliott Hughes
143f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifdef WITH_JNI_STACK_CHECK
144f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project# define COMPUTE_STACK_SUM(_self)   computeStackSum(_self);
145f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project# define CHECK_STACK_SUM(_self)     checkStackSum(_self);
1460647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes
1470647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes/*
1480647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes * Compute a CRC on the entire interpreted stack.
1490647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes *
1500647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes * Would be nice to compute it on "self" as well, but there are parts of
1510647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes * the Thread that can be altered by other threads (e.g. prev/next pointers).
1520647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes */
1530647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughesstatic void computeStackSum(Thread* self) {
15430bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee    const u1* low = (const u1*)SAVEAREA_FROM_FP(self->interpSave.curFrame);
1550647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    u4 crc = dvmInitCrc32();
1560647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    self->stackCrc = 0;
1570647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    crc = dvmComputeCrc32(crc, low, self->interpStackStart - low);
1580647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    self->stackCrc = crc;
1590647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes}
1600647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes
1610647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes/*
1620647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes * Compute a CRC on the entire interpreted stack, and compare it to what
1630647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes * we previously computed.
1640647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes *
1650647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes * We can execute JNI directly from native code without calling in from
1660647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes * interpreted code during VM initialization and immediately after JNI
1670647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes * thread attachment.  Another opportunity exists during JNI_OnLoad.  Rather
1680647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes * than catching these cases we just ignore them here, which is marginally
1690647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes * less accurate but reduces the amount of code we have to touch with #ifdefs.
1700647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes */
1710647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughesstatic void checkStackSum(Thread* self) {
17230bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee    const u1* low = (const u1*)SAVEAREA_FROM_FP(self->interpSave.curFrame);
1730647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    u4 stackCrc = self->stackCrc;
1740647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    self->stackCrc = 0;
1750647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    u4 crc = dvmInitCrc32();
1760647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    crc = dvmComputeCrc32(crc, low, self->interpStackStart - low);
1770647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    if (crc != stackCrc) {
1780647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes        const Method* meth = dvmGetCurrentJNIMethod();
17930bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee        if (dvmComputeExactFrameDepth(self->interpSave.curFrame) == 1) {
180062bf509a77fce9dfcb7e7b2e401cf2a124d83d5Steve Block            ALOGD("JNI: bad stack CRC (0x%08x) -- okay during init", stackCrc);
1810647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes        } else if (strcmp(meth->name, "nativeLoad") == 0 &&
1820647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes                (strcmp(meth->clazz->descriptor, "Ljava/lang/Runtime;") == 0)) {
183062bf509a77fce9dfcb7e7b2e401cf2a124d83d5Steve Block            ALOGD("JNI: bad stack CRC (0x%08x) -- okay during JNI_OnLoad", stackCrc);
1840647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes        } else {
185e8e1ddccd616e8226b7cc1e4e9fdb327429249e8Steve Block            ALOGW("JNI: bad stack CRC (%08x vs %08x)", crc, stackCrc);
18685e8913705f23a5e799690134746219f64498f29Elliott Hughes            ReportJniError();
1870647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes        }
1880647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    }
1890647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    self->stackCrc = (u4) -1;       /* make logic errors more noticeable */
1900647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes}
1910647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes
192f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#else
193f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project# define COMPUTE_STACK_SUM(_self)   ((void)0)
194f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project# define CHECK_STACK_SUM(_self)     ((void)0)
195f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
196f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
197f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
198f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
199f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * ===========================================================================
200f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *      Utility functions
201f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * ===========================================================================
202f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
203f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
204f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
205f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Entry/exit processing for all JNI calls.
206f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
2070647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes * We skip the (curiously expensive) thread-local storage lookup on our Thread*.
2080647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes * If the caller has passed the wrong JNIEnv in, we're going to be accessing unsynchronized
209f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * structures from more than one thread, and things are going to fail
210f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * in bizarre ways.  This is only sensible if the native code has been
211f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * fully exercised with CheckJNI enabled.
212f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
2130647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughesclass ScopedJniThreadState {
2140647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughespublic:
2150647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    explicit ScopedJniThreadState(JNIEnv* env) {
216de68817bdae0ca038d824ba79a70ac17cae405e6Elliott Hughes        mSelf = ((JNIEnvExt*) env)->self;
217de68817bdae0ca038d824ba79a70ac17cae405e6Elliott Hughes
218de68817bdae0ca038d824ba79a70ac17cae405e6Elliott Hughes        if (UNLIKELY(gDvmJni.workAroundAppJniBugs)) {
219de68817bdae0ca038d824ba79a70ac17cae405e6Elliott Hughes            // When emulating direct pointers with indirect references, it's critical
220de68817bdae0ca038d824ba79a70ac17cae405e6Elliott Hughes            // that we use the correct per-thread indirect reference table.
221de68817bdae0ca038d824ba79a70ac17cae405e6Elliott Hughes            Thread* self = gDvmJni.workAroundAppJniBugs ? dvmThreadSelf() : mSelf;
222de68817bdae0ca038d824ba79a70ac17cae405e6Elliott Hughes            if (self != mSelf) {
223c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block                ALOGE("JNI ERROR: env->self != thread-self (%p vs. %p); auto-correcting", mSelf, self);
224de68817bdae0ca038d824ba79a70ac17cae405e6Elliott Hughes                mSelf = self;
225de68817bdae0ca038d824ba79a70ac17cae405e6Elliott Hughes            }
226de68817bdae0ca038d824ba79a70ac17cae405e6Elliott Hughes        }
227de68817bdae0ca038d824ba79a70ac17cae405e6Elliott Hughes
2280647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes        CHECK_STACK_SUM(mSelf);
2290647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes        dvmChangeStatus(mSelf, THREAD_RUNNING);
2300647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    }
2310647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes
2320647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    ~ScopedJniThreadState() {
2330647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes        dvmChangeStatus(mSelf, THREAD_NATIVE);
2340647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes        COMPUTE_STACK_SUM(mSelf);
2350647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    }
2360647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes
237de68817bdae0ca038d824ba79a70ac17cae405e6Elliott Hughes    inline Thread* self() {
2380647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes        return mSelf;
2390647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    }
2400647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes
2410647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughesprivate:
2420647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    Thread* mSelf;
2430647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes
2440647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    // Disallow copy and assignment.
2450647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    ScopedJniThreadState(const ScopedJniThreadState&);
2460647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    void operator=(const ScopedJniThreadState&);
2470647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes};
248f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
249f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#define kGlobalRefsTableInitialSize 512
250ab00d455ea67fbf4090567bb09ead8017896ea61Andy McFadden#define kGlobalRefsTableMaxSize     51200       /* arbitrary, must be < 64K */
251f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#define kGrefWaterInterval          100
252f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#define kTrackGrefUsage             true
253f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
254e4c3b5ef3b418ea50f577a850bdbdfaf97718601Carl Shapiro#define kWeakGlobalRefsTableInitialSize 16
255e4c3b5ef3b418ea50f577a850bdbdfaf97718601Carl Shapiro
256c26bb63b50c7a855d25b396b1bf23a3aa6929b48Andy McFadden#define kPinTableInitialSize        16
257c26bb63b50c7a855d25b396b1bf23a3aa6929b48Andy McFadden#define kPinTableMaxSize            1024
258c26bb63b50c7a855d25b396b1bf23a3aa6929b48Andy McFadden#define kPinComplainThreshold       10
259c26bb63b50c7a855d25b396b1bf23a3aa6929b48Andy McFadden
26023ba9600c0207ef406513fce4c0278796e0b9415Elliott Hughesbool dvmJniStartup() {
261ce0968340f9ddd54f20e38d4946bfd2ef8f1f343Elliott Hughes    if (!gDvm.jniGlobalRefTable.init(kGlobalRefsTableInitialSize,
262e4c3b5ef3b418ea50f577a850bdbdfaf97718601Carl Shapiro                                 kGlobalRefsTableMaxSize,
26323ba9600c0207ef406513fce4c0278796e0b9415Elliott Hughes                                 kIndirectKindGlobal)) {
264e4c3b5ef3b418ea50f577a850bdbdfaf97718601Carl Shapiro        return false;
26523ba9600c0207ef406513fce4c0278796e0b9415Elliott Hughes    }
266ce0968340f9ddd54f20e38d4946bfd2ef8f1f343Elliott Hughes    if (!gDvm.jniWeakGlobalRefTable.init(kWeakGlobalRefsTableInitialSize,
267e4c3b5ef3b418ea50f577a850bdbdfaf97718601Carl Shapiro                                 kGlobalRefsTableMaxSize,
26823ba9600c0207ef406513fce4c0278796e0b9415Elliott Hughes                                 kIndirectKindWeakGlobal)) {
269d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden        return false;
27023ba9600c0207ef406513fce4c0278796e0b9415Elliott Hughes    }
271f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
272f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmInitMutex(&gDvm.jniGlobalRefLock);
273e4c3b5ef3b418ea50f577a850bdbdfaf97718601Carl Shapiro    dvmInitMutex(&gDvm.jniWeakGlobalRefLock);
274f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    gDvm.jniGlobalRefLoMark = 0;
275f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    gDvm.jniGlobalRefHiMark = kGrefWaterInterval * 2;
276f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
27723ba9600c0207ef406513fce4c0278796e0b9415Elliott Hughes    if (!dvmInitReferenceTable(&gDvm.jniPinRefTable, kPinTableInitialSize, kPinTableMaxSize)) {
278c26bb63b50c7a855d25b396b1bf23a3aa6929b48Andy McFadden        return false;
27923ba9600c0207ef406513fce4c0278796e0b9415Elliott Hughes    }
280c26bb63b50c7a855d25b396b1bf23a3aa6929b48Andy McFadden
281c26bb63b50c7a855d25b396b1bf23a3aa6929b48Andy McFadden    dvmInitMutex(&gDvm.jniPinRefLock);
282c26bb63b50c7a855d25b396b1bf23a3aa6929b48Andy McFadden
283f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return true;
284f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
285f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
28623ba9600c0207ef406513fce4c0278796e0b9415Elliott Hughesvoid dvmJniShutdown() {
287ce0968340f9ddd54f20e38d4946bfd2ef8f1f343Elliott Hughes    gDvm.jniGlobalRefTable.destroy();
288ce0968340f9ddd54f20e38d4946bfd2ef8f1f343Elliott Hughes    gDvm.jniWeakGlobalRefTable.destroy();
28996516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden    dvmClearReferenceTable(&gDvm.jniPinRefTable);
290f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
291f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
292f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
293f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Find the JNIEnv associated with the current thread.
294f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
295f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Currently stored in the Thread struct.  Could also just drop this into
296f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * thread-local storage.
297f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
29823ba9600c0207ef406513fce4c0278796e0b9415Elliott HughesJNIEnvExt* dvmGetJNIEnvForThread() {
299f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Thread* self = dvmThreadSelf();
30023ba9600c0207ef406513fce4c0278796e0b9415Elliott Hughes    if (self == NULL) {
301f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return NULL;
30223ba9600c0207ef406513fce4c0278796e0b9415Elliott Hughes    }
303f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return (JNIEnvExt*) dvmGetThreadJNIEnv(self);
304f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
305f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
306f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
307d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden * Convert an indirect reference to an Object reference.  The indirect
308d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden * reference may be local, global, or weak-global.
309d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden *
310c759b9f089e8e09df335a030d0555366d9395aebAndy McFadden * If "jobj" is NULL, or is a weak global reference whose reference has
311c759b9f089e8e09df335a030d0555366d9395aebAndy McFadden * been cleared, this returns NULL.  If jobj is an invalid indirect
312c759b9f089e8e09df335a030d0555366d9395aebAndy McFadden * reference, kInvalidIndirectRefObject is returned.
313fbaf4f9ba8eb75c4e6cb0b5d6bbc31e386548c5aMark Gordon *
314fbaf4f9ba8eb75c4e6cb0b5d6bbc31e386548c5aMark Gordon * Note "env" may be NULL when decoding global references.
315d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden */
316de68817bdae0ca038d824ba79a70ac17cae405e6Elliott HughesObject* dvmDecodeIndirectRef(Thread* self, jobject jobj) {
31723ba9600c0207ef406513fce4c0278796e0b9415Elliott Hughes    if (jobj == NULL) {
318d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden        return NULL;
31923ba9600c0207ef406513fce4c0278796e0b9415Elliott Hughes    }
320d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden
321ce0968340f9ddd54f20e38d4946bfd2ef8f1f343Elliott Hughes    switch (indirectRefKind(jobj)) {
322d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden    case kIndirectKindLocal:
323ddbd6f44af283415162ea7bb1b4e7ef77c8de492Elliott Hughes        {
324de68817bdae0ca038d824ba79a70ac17cae405e6Elliott Hughes            Object* result = self->jniLocalRefTable.get(jobj);
325de68817bdae0ca038d824ba79a70ac17cae405e6Elliott Hughes            if (UNLIKELY(result == NULL)) {
326c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block                ALOGE("JNI ERROR (app bug): use of deleted local reference (%p)", jobj);
32785e8913705f23a5e799690134746219f64498f29Elliott Hughes                ReportJniError();
328ddbd6f44af283415162ea7bb1b4e7ef77c8de492Elliott Hughes            }
329ddbd6f44af283415162ea7bb1b4e7ef77c8de492Elliott Hughes            return result;
330ddbd6f44af283415162ea7bb1b4e7ef77c8de492Elliott Hughes        }
331d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden    case kIndirectKindGlobal:
332d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden        {
333d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden            // TODO: find a way to avoid the mutex activity here
334d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden            IndirectRefTable* pRefTable = &gDvm.jniGlobalRefTable;
33589383030aca8f77aeab73540404ba332ce5ac035Elliott Hughes            ScopedPthreadMutexLock lock(&gDvm.jniGlobalRefLock);
336ddbd6f44af283415162ea7bb1b4e7ef77c8de492Elliott Hughes            Object* result = pRefTable->get(jobj);
337de68817bdae0ca038d824ba79a70ac17cae405e6Elliott Hughes            if (UNLIKELY(result == NULL)) {
338c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block                ALOGE("JNI ERROR (app bug): use of deleted global reference (%p)", jobj);
33985e8913705f23a5e799690134746219f64498f29Elliott Hughes                ReportJniError();
340ddbd6f44af283415162ea7bb1b4e7ef77c8de492Elliott Hughes            }
341ddbd6f44af283415162ea7bb1b4e7ef77c8de492Elliott Hughes            return result;
342d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden        }
343d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden    case kIndirectKindWeakGlobal:
344d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden        {
345ddbd6f44af283415162ea7bb1b4e7ef77c8de492Elliott Hughes            // TODO: find a way to avoid the mutex activity here
346ddbd6f44af283415162ea7bb1b4e7ef77c8de492Elliott Hughes            IndirectRefTable* pRefTable = &gDvm.jniWeakGlobalRefTable;
347ddbd6f44af283415162ea7bb1b4e7ef77c8de492Elliott Hughes            ScopedPthreadMutexLock lock(&gDvm.jniWeakGlobalRefLock);
348ddbd6f44af283415162ea7bb1b4e7ef77c8de492Elliott Hughes            Object* result = pRefTable->get(jobj);
349259a8a5154c63a793ea0ee438d146acda7d990b6Elliott Hughes            if (result == kClearedJniWeakGlobal) {
350c759b9f089e8e09df335a030d0555366d9395aebAndy McFadden                result = NULL;
351de68817bdae0ca038d824ba79a70ac17cae405e6Elliott Hughes            } else if (UNLIKELY(result == NULL)) {
352c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block                ALOGE("JNI ERROR (app bug): use of deleted weak global reference (%p)", jobj);
35385e8913705f23a5e799690134746219f64498f29Elliott Hughes                ReportJniError();
354c759b9f089e8e09df335a030d0555366d9395aebAndy McFadden            }
355ce0968340f9ddd54f20e38d4946bfd2ef8f1f343Elliott Hughes            return result;
356d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden        }
357d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden    case kIndirectKindInvalid:
358d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden    default:
359de68817bdae0ca038d824ba79a70ac17cae405e6Elliott Hughes        if (UNLIKELY(gDvmJni.workAroundAppJniBugs)) {
360ea333384b92db9c400be1b4c8cb6992d9ba5f14dElliott Hughes            // Assume an invalid local reference is actually a direct pointer.
361ea333384b92db9c400be1b4c8cb6992d9ba5f14dElliott Hughes            return reinterpret_cast<Object*>(jobj);
362ea333384b92db9c400be1b4c8cb6992d9ba5f14dElliott Hughes        }
363e8e1ddccd616e8226b7cc1e4e9fdb327429249e8Steve Block        ALOGW("Invalid indirect reference %p in decodeIndirectRef", jobj);
36485e8913705f23a5e799690134746219f64498f29Elliott Hughes        ReportJniError();
365ce0968340f9ddd54f20e38d4946bfd2ef8f1f343Elliott Hughes        return kInvalidIndirectRefObject;
366d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden    }
367eb9cbc33ee450d9c237a48273595d9f2a05be342Andy McFadden}
368f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
369de68817bdae0ca038d824ba79a70ac17cae405e6Elliott Hughesstatic void AddLocalReferenceFailure(IndirectRefTable* pRefTable) {
370de68817bdae0ca038d824ba79a70ac17cae405e6Elliott Hughes    pRefTable->dump("JNI local");
371c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block    ALOGE("Failed adding to JNI local ref table (has %zd entries)", pRefTable->capacity());
37285e8913705f23a5e799690134746219f64498f29Elliott Hughes    ReportJniError(); // spec says call FatalError; this is equivalent
373de68817bdae0ca038d824ba79a70ac17cae405e6Elliott Hughes}
374de68817bdae0ca038d824ba79a70ac17cae405e6Elliott Hughes
375f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
376f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Add a local reference for an object to the current stack frame.  When
377f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the native function returns, the reference will be discarded.
378f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
379f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We need to allow the same reference to be added multiple times.
380f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
381f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This will be called on otherwise unreferenced objects.  We cannot do
382f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * GC allocations here, and it's best if we don't grab a mutex.
383f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
384de68817bdae0ca038d824ba79a70ac17cae405e6Elliott Hughesstatic inline jobject addLocalReference(Thread* self, Object* obj) {
38523ba9600c0207ef406513fce4c0278796e0b9415Elliott Hughes    if (obj == NULL) {
386f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return NULL;
38723ba9600c0207ef406513fce4c0278796e0b9415Elliott Hughes    }
388f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
389de68817bdae0ca038d824ba79a70ac17cae405e6Elliott Hughes    IndirectRefTable* pRefTable = &self->jniLocalRefTable;
390de68817bdae0ca038d824ba79a70ac17cae405e6Elliott Hughes    void* curFrame = self->interpSave.curFrame;
391d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden    u4 cookie = SAVEAREA_FROM_FP(curFrame)->xtra.localRefCookie;
392ce0968340f9ddd54f20e38d4946bfd2ef8f1f343Elliott Hughes    jobject jobj = (jobject) pRefTable->add(cookie, obj);
393de68817bdae0ca038d824ba79a70ac17cae405e6Elliott Hughes    if (UNLIKELY(jobj == NULL)) {
394de68817bdae0ca038d824ba79a70ac17cae405e6Elliott Hughes        AddLocalReferenceFailure(pRefTable);
395d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden    }
39685e8913705f23a5e799690134746219f64498f29Elliott Hughes
397de68817bdae0ca038d824ba79a70ac17cae405e6Elliott Hughes    if (UNLIKELY(gDvmJni.workAroundAppJniBugs)) {
398ea333384b92db9c400be1b4c8cb6992d9ba5f14dElliott Hughes        // Hand out direct pointers to support broken old apps.
399ea333384b92db9c400be1b4c8cb6992d9ba5f14dElliott Hughes        return reinterpret_cast<jobject>(obj);
400ea333384b92db9c400be1b4c8cb6992d9ba5f14dElliott Hughes    }
401d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden    return jobj;
402ab00d455ea67fbf4090567bb09ead8017896ea61Andy McFadden}
403ab00d455ea67fbf4090567bb09ead8017896ea61Andy McFadden
404ab00d455ea67fbf4090567bb09ead8017896ea61Andy McFadden/*
405f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Ensure that at least "capacity" references can be held in the local
406f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * refs table of the current thread.
407f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
408de68817bdae0ca038d824ba79a70ac17cae405e6Elliott Hughesstatic bool ensureLocalCapacity(Thread* self, int capacity) {
409de68817bdae0ca038d824ba79a70ac17cae405e6Elliott Hughes    int numEntries = self->jniLocalRefTable.capacity();
410d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden    // TODO: this isn't quite right, since "numEntries" includes holes
411d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden    return ((kJniLocalRefMax - numEntries) >= capacity);
412f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
413f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
414f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
415f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Explicitly delete a reference from the local list.
416f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
417de68817bdae0ca038d824ba79a70ac17cae405e6Elliott Hughesstatic void deleteLocalReference(Thread* self, jobject jobj) {
41823ba9600c0207ef406513fce4c0278796e0b9415Elliott Hughes    if (jobj == NULL) {
419f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return;
42023ba9600c0207ef406513fce4c0278796e0b9415Elliott Hughes    }
421f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
422de68817bdae0ca038d824ba79a70ac17cae405e6Elliott Hughes    IndirectRefTable* pRefTable = &self->jniLocalRefTable;
423de68817bdae0ca038d824ba79a70ac17cae405e6Elliott Hughes    void* curFrame = self->interpSave.curFrame;
4243f04fa049734772a945243d64d6ce9a34b39b730Elliott Hughes    u4 cookie = SAVEAREA_FROM_FP(curFrame)->xtra.localRefCookie;
425ce0968340f9ddd54f20e38d4946bfd2ef8f1f343Elliott Hughes    if (!pRefTable->remove(cookie, jobj)) {
426d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden        /*
427d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden         * Attempting to delete a local reference that is not in the
428d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden         * topmost local reference frame is a no-op.  DeleteLocalRef returns
429d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden         * void and doesn't throw any exceptions, but we should probably
430d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden         * complain about it so the user will notice that things aren't
431d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden         * going quite the way they expect.
432d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden         */
433e8e1ddccd616e8226b7cc1e4e9fdb327429249e8Steve Block        ALOGW("JNI WARNING: DeleteLocalRef(%p) failed to find entry", jobj);
434d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden    }
435f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
436f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
437f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
438f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Add a global reference for an object.
439f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
440f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We may add the same object more than once.  Add/remove calls are paired,
441f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * so it needs to appear on the list multiple times.
442f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
44323ba9600c0207ef406513fce4c0278796e0b9415Elliott Hughesstatic jobject addGlobalReference(Object* obj) {
44423ba9600c0207ef406513fce4c0278796e0b9415Elliott Hughes    if (obj == NULL) {
445f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return NULL;
44623ba9600c0207ef406513fce4c0278796e0b9415Elliott Hughes    }
447f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4484308417beec548c2b2c06ecec4f7f4a965b09fb2Steve Block    //ALOGI("adding obj=%p", obj);
449f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    //dvmDumpThread(dvmThreadSelf(), false);
450f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
451c6d2470eec726ae0ad95e4fd2d9d7da7cb2cdcbaDan Bornstein    if (false && dvmIsClassObject((Object*)obj)) {
452f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        ClassObject* clazz = (ClassObject*) obj;
4534308417beec548c2b2c06ecec4f7f4a965b09fb2Steve Block        ALOGI("-------");
4544308417beec548c2b2c06ecec4f7f4a965b09fb2Steve Block        ALOGI("Adding global ref on class %s", clazz->descriptor);
455f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmDumpThread(dvmThreadSelf(), false);
456f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
457f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (false && ((Object*)obj)->clazz == gDvm.classJavaLangString) {
458f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        StringObject* strObj = (StringObject*) obj;
459f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        char* str = dvmCreateCstrFromString(strObj);
460f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (strcmp(str, "sync-response") == 0) {
4614308417beec548c2b2c06ecec4f7f4a965b09fb2Steve Block            ALOGI("-------");
4624308417beec548c2b2c06ecec4f7f4a965b09fb2Steve Block            ALOGI("Adding global ref on string '%s'", str);
463f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmDumpThread(dvmThreadSelf(), false);
464f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            //dvmAbort();
465f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
466f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        free(str);
467f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
468f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (false && ((Object*)obj)->clazz == gDvm.classArrayByte) {
469f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        ArrayObject* arrayObj = (ArrayObject*) obj;
470d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden        if (arrayObj->length == 8192 /*&&
471d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden            dvmReferenceTableEntries(&gDvm.jniGlobalRefTable) > 400*/)
472f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        {
4734308417beec548c2b2c06ecec4f7f4a965b09fb2Steve Block            ALOGI("Adding global ref on byte array %p (len=%d)",
474f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                arrayObj, arrayObj->length);
475f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmDumpThread(dvmThreadSelf(), false);
476f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
477f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
478d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden
47989383030aca8f77aeab73540404ba332ce5ac035Elliott Hughes    ScopedPthreadMutexLock lock(&gDvm.jniGlobalRefLock);
480d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden
481d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden    /*
482d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden     * Throwing an exception on failure is problematic, because JNI code
483d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden     * may not be expecting an exception, and things sort of cascade.  We
484d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden     * want to have a hard limit to catch leaks during debugging, but this
485d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden     * otherwise needs to expand until memory is consumed.  As a practical
486d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden     * matter, if we have many thousands of global references, chances are
487d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden     * we're either leaking global ref table entries or we're going to
488d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden     * run out of space in the GC heap.
489d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden     */
490ce0968340f9ddd54f20e38d4946bfd2ef8f1f343Elliott Hughes    jobject jobj = (jobject) gDvm.jniGlobalRefTable.add(IRT_FIRST_SEGMENT, obj);
491d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden    if (jobj == NULL) {
492ce0968340f9ddd54f20e38d4946bfd2ef8f1f343Elliott Hughes        gDvm.jniGlobalRefTable.dump("JNI global");
493c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block        ALOGE("Failed adding to JNI global ref table (%zd entries)",
494ce0968340f9ddd54f20e38d4946bfd2ef8f1f343Elliott Hughes                gDvm.jniGlobalRefTable.capacity());
49585e8913705f23a5e799690134746219f64498f29Elliott Hughes        ReportJniError();
496d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden    }
497d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden
49823ba9600c0207ef406513fce4c0278796e0b9415Elliott Hughes    LOGVV("GREF add %p  (%s.%s)", obj,
499d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden        dvmGetCurrentJNIMethod()->clazz->descriptor,
500d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden        dvmGetCurrentJNIMethod()->name);
501d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden
502d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden    /* GREF usage tracking; should probably be disabled for production env */
503d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden    if (kTrackGrefUsage && gDvm.jniGrefLimit != 0) {
504ce0968340f9ddd54f20e38d4946bfd2ef8f1f343Elliott Hughes        int count = gDvm.jniGlobalRefTable.capacity();
505d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden        // TODO: adjust for "holes"
506d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden        if (count > gDvm.jniGlobalRefHiMark) {
507062bf509a77fce9dfcb7e7b2e401cf2a124d83d5Steve Block            ALOGD("GREF has increased to %d", count);
508d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden            gDvm.jniGlobalRefHiMark += kGrefWaterInterval;
509d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden            gDvm.jniGlobalRefLoMark += kGrefWaterInterval;
510d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden
511d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden            /* watch for "excessive" use; not generally appropriate */
512d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden            if (count >= gDvm.jniGrefLimit) {
513a5f3ed80b3b058b006ee2b09915d1400cebd0442Elliott Hughes                if (gDvmJni.warnOnly) {
514e8e1ddccd616e8226b7cc1e4e9fdb327429249e8Steve Block                    ALOGW("Excessive JNI global references (%d)", count);
515a5f3ed80b3b058b006ee2b09915d1400cebd0442Elliott Hughes                } else {
516ce0968340f9ddd54f20e38d4946bfd2ef8f1f343Elliott Hughes                    gDvm.jniGlobalRefTable.dump("JNI global");
517c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block                    ALOGE("Excessive JNI global references (%d)", count);
51885e8913705f23a5e799690134746219f64498f29Elliott Hughes                    ReportJniError();
519d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden                }
520d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden            }
521d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden        }
522d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden    }
523d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden    return jobj;
524f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
525f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
52623ba9600c0207ef406513fce4c0278796e0b9415Elliott Hughesstatic jobject addWeakGlobalReference(Object* obj) {
52789383030aca8f77aeab73540404ba332ce5ac035Elliott Hughes    if (obj == NULL) {
528e4c3b5ef3b418ea50f577a850bdbdfaf97718601Carl Shapiro        return NULL;
52989383030aca8f77aeab73540404ba332ce5ac035Elliott Hughes    }
53089383030aca8f77aeab73540404ba332ce5ac035Elliott Hughes
53189383030aca8f77aeab73540404ba332ce5ac035Elliott Hughes    ScopedPthreadMutexLock lock(&gDvm.jniWeakGlobalRefLock);
532e4c3b5ef3b418ea50f577a850bdbdfaf97718601Carl Shapiro    IndirectRefTable *table = &gDvm.jniWeakGlobalRefTable;
533ce0968340f9ddd54f20e38d4946bfd2ef8f1f343Elliott Hughes    jobject jobj = (jobject) table->add(IRT_FIRST_SEGMENT, obj);
534e4c3b5ef3b418ea50f577a850bdbdfaf97718601Carl Shapiro    if (jobj == NULL) {
5355552e62455d486d19e5986a67ae2545411d50fbeJeff Brown        gDvm.jniWeakGlobalRefTable.dump("JNI weak global");
536c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block        ALOGE("Failed adding to JNI weak global ref table (%zd entries)", table->capacity());
53785e8913705f23a5e799690134746219f64498f29Elliott Hughes        ReportJniError();
538e4c3b5ef3b418ea50f577a850bdbdfaf97718601Carl Shapiro    }
539e4c3b5ef3b418ea50f577a850bdbdfaf97718601Carl Shapiro    return jobj;
540e4c3b5ef3b418ea50f577a850bdbdfaf97718601Carl Shapiro}
541e4c3b5ef3b418ea50f577a850bdbdfaf97718601Carl Shapiro
54223ba9600c0207ef406513fce4c0278796e0b9415Elliott Hughesstatic void deleteWeakGlobalReference(jobject jobj) {
54389383030aca8f77aeab73540404ba332ce5ac035Elliott Hughes    if (jobj == NULL) {
544e4c3b5ef3b418ea50f577a850bdbdfaf97718601Carl Shapiro        return;
54589383030aca8f77aeab73540404ba332ce5ac035Elliott Hughes    }
54689383030aca8f77aeab73540404ba332ce5ac035Elliott Hughes
54789383030aca8f77aeab73540404ba332ce5ac035Elliott Hughes    ScopedPthreadMutexLock lock(&gDvm.jniWeakGlobalRefLock);
548e4c3b5ef3b418ea50f577a850bdbdfaf97718601Carl Shapiro    IndirectRefTable *table = &gDvm.jniWeakGlobalRefTable;
549ce0968340f9ddd54f20e38d4946bfd2ef8f1f343Elliott Hughes    if (!table->remove(IRT_FIRST_SEGMENT, jobj)) {
550e8e1ddccd616e8226b7cc1e4e9fdb327429249e8Steve Block        ALOGW("JNI: DeleteWeakGlobalRef(%p) failed to find entry", jobj);
551e4c3b5ef3b418ea50f577a850bdbdfaf97718601Carl Shapiro    }
552e4c3b5ef3b418ea50f577a850bdbdfaf97718601Carl Shapiro}
553e4c3b5ef3b418ea50f577a850bdbdfaf97718601Carl Shapiro
554f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
555f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Remove a global reference.  In most cases it's the entry most recently
556f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * added, which makes this pretty quick.
557f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
558f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Thought: if it's not the most recent entry, just null it out.  When we
559f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * fill up, do a compaction pass before we expand the list.
560f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
56123ba9600c0207ef406513fce4c0278796e0b9415Elliott Hughesstatic void deleteGlobalReference(jobject jobj) {
56223ba9600c0207ef406513fce4c0278796e0b9415Elliott Hughes    if (jobj == NULL) {
563f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return;
56423ba9600c0207ef406513fce4c0278796e0b9415Elliott Hughes    }
565f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
56689383030aca8f77aeab73540404ba332ce5ac035Elliott Hughes    ScopedPthreadMutexLock lock(&gDvm.jniGlobalRefLock);
567ce0968340f9ddd54f20e38d4946bfd2ef8f1f343Elliott Hughes    if (!gDvm.jniGlobalRefTable.remove(IRT_FIRST_SEGMENT, jobj)) {
568e8e1ddccd616e8226b7cc1e4e9fdb327429249e8Steve Block        ALOGW("JNI: DeleteGlobalRef(%p) failed to find entry", jobj);
56989383030aca8f77aeab73540404ba332ce5ac035Elliott Hughes        return;
570d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden    }
571d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden
572d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden    if (kTrackGrefUsage && gDvm.jniGrefLimit != 0) {
573ce0968340f9ddd54f20e38d4946bfd2ef8f1f343Elliott Hughes        int count = gDvm.jniGlobalRefTable.capacity();
574d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden        // TODO: not quite right, need to subtract holes
575d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden        if (count < gDvm.jniGlobalRefLoMark) {
576062bf509a77fce9dfcb7e7b2e401cf2a124d83d5Steve Block            ALOGD("GREF has decreased to %d", count);
577d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden            gDvm.jniGlobalRefHiMark -= kGrefWaterInterval;
578d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden            gDvm.jniGlobalRefLoMark -= kGrefWaterInterval;
579d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden        }
580d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden    }
581f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
582f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
583f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
584ab00d455ea67fbf4090567bb09ead8017896ea61Andy McFadden * Objects don't currently move, so we just need to create a reference
585ab00d455ea67fbf4090567bb09ead8017896ea61Andy McFadden * that will ensure the array object isn't collected.
586ab00d455ea67fbf4090567bb09ead8017896ea61Andy McFadden *
587c26bb63b50c7a855d25b396b1bf23a3aa6929b48Andy McFadden * We use a separate reference table, which is part of the GC root set.
588ab00d455ea67fbf4090567bb09ead8017896ea61Andy McFadden */
58923ba9600c0207ef406513fce4c0278796e0b9415Elliott Hughesstatic void pinPrimitiveArray(ArrayObject* arrayObj) {
59089383030aca8f77aeab73540404ba332ce5ac035Elliott Hughes    if (arrayObj == NULL) {
591c26bb63b50c7a855d25b396b1bf23a3aa6929b48Andy McFadden        return;
59289383030aca8f77aeab73540404ba332ce5ac035Elliott Hughes    }
59389383030aca8f77aeab73540404ba332ce5ac035Elliott Hughes
59489383030aca8f77aeab73540404ba332ce5ac035Elliott Hughes    ScopedPthreadMutexLock lock(&gDvm.jniPinRefLock);
595c26bb63b50c7a855d25b396b1bf23a3aa6929b48Andy McFadden
596c26bb63b50c7a855d25b396b1bf23a3aa6929b48Andy McFadden    if (!dvmAddToReferenceTable(&gDvm.jniPinRefTable, (Object*)arrayObj)) {
597c26bb63b50c7a855d25b396b1bf23a3aa6929b48Andy McFadden        dvmDumpReferenceTable(&gDvm.jniPinRefTable, "JNI pinned array");
598c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block        ALOGE("Failed adding to JNI pinned array ref table (%d entries)",
599e4c3b5ef3b418ea50f577a850bdbdfaf97718601Carl Shapiro           (int) dvmReferenceTableEntries(&gDvm.jniPinRefTable));
60085e8913705f23a5e799690134746219f64498f29Elliott Hughes        ReportJniError();
601c26bb63b50c7a855d25b396b1bf23a3aa6929b48Andy McFadden    }
602c26bb63b50c7a855d25b396b1bf23a3aa6929b48Andy McFadden
603c26bb63b50c7a855d25b396b1bf23a3aa6929b48Andy McFadden    /*
604c26bb63b50c7a855d25b396b1bf23a3aa6929b48Andy McFadden     * If we're watching global ref usage, also keep an eye on these.
605c26bb63b50c7a855d25b396b1bf23a3aa6929b48Andy McFadden     *
606c26bb63b50c7a855d25b396b1bf23a3aa6929b48Andy McFadden     * The total number of pinned primitive arrays should be pretty small.
607c26bb63b50c7a855d25b396b1bf23a3aa6929b48Andy McFadden     * A single array should not be pinned more than once or twice; any
608c26bb63b50c7a855d25b396b1bf23a3aa6929b48Andy McFadden     * more than that is a strong indicator that a Release function is
609c26bb63b50c7a855d25b396b1bf23a3aa6929b48Andy McFadden     * not being called.
610c26bb63b50c7a855d25b396b1bf23a3aa6929b48Andy McFadden     */
611c26bb63b50c7a855d25b396b1bf23a3aa6929b48Andy McFadden    if (kTrackGrefUsage && gDvm.jniGrefLimit != 0) {
612c26bb63b50c7a855d25b396b1bf23a3aa6929b48Andy McFadden        int count = 0;
613c26bb63b50c7a855d25b396b1bf23a3aa6929b48Andy McFadden        Object** ppObj = gDvm.jniPinRefTable.table;
614c26bb63b50c7a855d25b396b1bf23a3aa6929b48Andy McFadden        while (ppObj < gDvm.jniPinRefTable.nextEntry) {
615c26bb63b50c7a855d25b396b1bf23a3aa6929b48Andy McFadden            if (*ppObj++ == (Object*) arrayObj)
616c26bb63b50c7a855d25b396b1bf23a3aa6929b48Andy McFadden                count++;
617c26bb63b50c7a855d25b396b1bf23a3aa6929b48Andy McFadden        }
618c26bb63b50c7a855d25b396b1bf23a3aa6929b48Andy McFadden
619c26bb63b50c7a855d25b396b1bf23a3aa6929b48Andy McFadden        if (count > kPinComplainThreshold) {
620e8e1ddccd616e8226b7cc1e4e9fdb327429249e8Steve Block            ALOGW("JNI: pin count on array %p (%s) is now %d",
621a62c3a0ab3fcdde37f47d16e9699a935ae7a8e88Carl Shapiro                arrayObj, arrayObj->clazz->descriptor, count);
622c26bb63b50c7a855d25b396b1bf23a3aa6929b48Andy McFadden            /* keep going */
623c26bb63b50c7a855d25b396b1bf23a3aa6929b48Andy McFadden        }
624c26bb63b50c7a855d25b396b1bf23a3aa6929b48Andy McFadden    }
625ab00d455ea67fbf4090567bb09ead8017896ea61Andy McFadden}
626ab00d455ea67fbf4090567bb09ead8017896ea61Andy McFadden
627ab00d455ea67fbf4090567bb09ead8017896ea61Andy McFadden/*
628ab00d455ea67fbf4090567bb09ead8017896ea61Andy McFadden * Un-pin the array object.  If an object was pinned twice, it must be
629ab00d455ea67fbf4090567bb09ead8017896ea61Andy McFadden * unpinned twice before it's free to move.
630ab00d455ea67fbf4090567bb09ead8017896ea61Andy McFadden */
63123ba9600c0207ef406513fce4c0278796e0b9415Elliott Hughesstatic void unpinPrimitiveArray(ArrayObject* arrayObj) {
63289383030aca8f77aeab73540404ba332ce5ac035Elliott Hughes    if (arrayObj == NULL) {
633c26bb63b50c7a855d25b396b1bf23a3aa6929b48Andy McFadden        return;
63489383030aca8f77aeab73540404ba332ce5ac035Elliott Hughes    }
635c26bb63b50c7a855d25b396b1bf23a3aa6929b48Andy McFadden
63689383030aca8f77aeab73540404ba332ce5ac035Elliott Hughes    ScopedPthreadMutexLock lock(&gDvm.jniPinRefLock);
637c26bb63b50c7a855d25b396b1bf23a3aa6929b48Andy McFadden    if (!dvmRemoveFromReferenceTable(&gDvm.jniPinRefTable,
638c26bb63b50c7a855d25b396b1bf23a3aa6929b48Andy McFadden            gDvm.jniPinRefTable.table, (Object*) arrayObj))
639c26bb63b50c7a855d25b396b1bf23a3aa6929b48Andy McFadden    {
640e8e1ddccd616e8226b7cc1e4e9fdb327429249e8Steve Block        ALOGW("JNI: unpinPrimitiveArray(%p) failed to find entry (valid=%d)",
6418bc8bf71a52e17d483021b4c9dc8e735d9bce3edElliott Hughes            arrayObj, dvmIsHeapAddress((Object*) arrayObj));
64289383030aca8f77aeab73540404ba332ce5ac035Elliott Hughes        return;
643c26bb63b50c7a855d25b396b1bf23a3aa6929b48Andy McFadden    }
644ab00d455ea67fbf4090567bb09ead8017896ea61Andy McFadden}
645ab00d455ea67fbf4090567bb09ead8017896ea61Andy McFadden
646ab00d455ea67fbf4090567bb09ead8017896ea61Andy McFadden/*
64792fa476a8802023b443af893817eb14fef18aaeaAndy McFadden * Dump the contents of the JNI reference tables to the log file.
64892fa476a8802023b443af893817eb14fef18aaeaAndy McFadden *
64992fa476a8802023b443af893817eb14fef18aaeaAndy McFadden * We only dump the local refs associated with the current thread.
65092fa476a8802023b443af893817eb14fef18aaeaAndy McFadden */
65123ba9600c0207ef406513fce4c0278796e0b9415Elliott Hughesvoid dvmDumpJniReferenceTables() {
65292fa476a8802023b443af893817eb14fef18aaeaAndy McFadden    Thread* self = dvmThreadSelf();
653de68817bdae0ca038d824ba79a70ac17cae405e6Elliott Hughes    self->jniLocalRefTable.dump("JNI local");
654ce0968340f9ddd54f20e38d4946bfd2ef8f1f343Elliott Hughes    gDvm.jniGlobalRefTable.dump("JNI global");
65592fa476a8802023b443af893817eb14fef18aaeaAndy McFadden    dvmDumpReferenceTable(&gDvm.jniPinRefTable, "JNI pinned array");
65692fa476a8802023b443af893817eb14fef18aaeaAndy McFadden}
65792fa476a8802023b443af893817eb14fef18aaeaAndy McFadden
658483eedc3f30dcaf7ddb2f1b928db8608d9d38ffeElliott Hughesvoid dvmDumpJniStats(DebugOutputTarget* target) {
659483eedc3f30dcaf7ddb2f1b928db8608d9d38ffeElliott Hughes    dvmPrintDebugMessage(target, "JNI: CheckJNI is %s", gDvmJni.useCheckJni ? "on" : "off");
660483eedc3f30dcaf7ddb2f1b928db8608d9d38ffeElliott Hughes    if (gDvmJni.forceCopy) {
661855a7de7fdc696a1ba1102acaf5a356375405462Elliott Hughes        dvmPrintDebugMessage(target, " (with forcecopy)");
662483eedc3f30dcaf7ddb2f1b928db8608d9d38ffeElliott Hughes    }
663483eedc3f30dcaf7ddb2f1b928db8608d9d38ffeElliott Hughes    dvmPrintDebugMessage(target, "; workarounds are %s", gDvmJni.workAroundAppJniBugs ? "on" : "off");
664483eedc3f30dcaf7ddb2f1b928db8608d9d38ffeElliott Hughes
665483eedc3f30dcaf7ddb2f1b928db8608d9d38ffeElliott Hughes    dvmLockMutex(&gDvm.jniPinRefLock);
666483eedc3f30dcaf7ddb2f1b928db8608d9d38ffeElliott Hughes    dvmPrintDebugMessage(target, "; pins=%d", dvmReferenceTableEntries(&gDvm.jniPinRefTable));
667483eedc3f30dcaf7ddb2f1b928db8608d9d38ffeElliott Hughes    dvmUnlockMutex(&gDvm.jniPinRefLock);
668483eedc3f30dcaf7ddb2f1b928db8608d9d38ffeElliott Hughes
669483eedc3f30dcaf7ddb2f1b928db8608d9d38ffeElliott Hughes    dvmLockMutex(&gDvm.jniGlobalRefLock);
670483eedc3f30dcaf7ddb2f1b928db8608d9d38ffeElliott Hughes    dvmPrintDebugMessage(target, "; globals=%d", gDvm.jniGlobalRefTable.capacity());
671483eedc3f30dcaf7ddb2f1b928db8608d9d38ffeElliott Hughes    dvmUnlockMutex(&gDvm.jniGlobalRefLock);
672483eedc3f30dcaf7ddb2f1b928db8608d9d38ffeElliott Hughes
673483eedc3f30dcaf7ddb2f1b928db8608d9d38ffeElliott Hughes    dvmLockMutex(&gDvm.jniWeakGlobalRefLock);
674483eedc3f30dcaf7ddb2f1b928db8608d9d38ffeElliott Hughes    size_t weaks = gDvm.jniWeakGlobalRefTable.capacity();
675483eedc3f30dcaf7ddb2f1b928db8608d9d38ffeElliott Hughes    if (weaks > 0) {
676483eedc3f30dcaf7ddb2f1b928db8608d9d38ffeElliott Hughes        dvmPrintDebugMessage(target, " (plus %d weak)", weaks);
677483eedc3f30dcaf7ddb2f1b928db8608d9d38ffeElliott Hughes    }
678483eedc3f30dcaf7ddb2f1b928db8608d9d38ffeElliott Hughes    dvmUnlockMutex(&gDvm.jniWeakGlobalRefLock);
679483eedc3f30dcaf7ddb2f1b928db8608d9d38ffeElliott Hughes
680483eedc3f30dcaf7ddb2f1b928db8608d9d38ffeElliott Hughes    dvmPrintDebugMessage(target, "\n\n");
681483eedc3f30dcaf7ddb2f1b928db8608d9d38ffeElliott Hughes}
682483eedc3f30dcaf7ddb2f1b928db8608d9d38ffeElliott Hughes
683f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
684f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Verify that a reference passed in from native code is one that the
685f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * code is allowed to have.
686f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
687f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * It's okay for native code to pass us a reference that:
6880083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden *  - was passed in as an argument when invoked by native code (and hence
6890083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden *    is in the JNI local refs table)
6900083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden *  - was returned to it from JNI (and is now in the local refs table)
691f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *  - is present in the JNI global refs table
692f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
693f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Used by -Xcheck:jni and GetObjectRefType.
694f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
695de68817bdae0ca038d824ba79a70ac17cae405e6Elliott HughesjobjectRefType dvmGetJNIRefType(Thread* self, jobject jobj) {
696d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden    /*
697d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden     * IndirectRefKind is currently defined as an exact match of
6980423f0e813a3807168fe5524405eb96675532097Andy McFadden     * jobjectRefType, so this is easy.  We have to decode it to determine
6990423f0e813a3807168fe5524405eb96675532097Andy McFadden     * if it's a valid reference and not merely valid-looking.
700d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden     */
701c759b9f089e8e09df335a030d0555366d9395aebAndy McFadden    assert(jobj != NULL);
702c759b9f089e8e09df335a030d0555366d9395aebAndy McFadden
703de68817bdae0ca038d824ba79a70ac17cae405e6Elliott Hughes    Object* obj = dvmDecodeIndirectRef(self, jobj);
704ea333384b92db9c400be1b4c8cb6992d9ba5f14dElliott Hughes    if (obj == reinterpret_cast<Object*>(jobj) && gDvmJni.workAroundAppJniBugs) {
705ea333384b92db9c400be1b4c8cb6992d9ba5f14dElliott Hughes        // If we're handing out direct pointers, check whether 'jobj' is a direct reference
706ea333384b92db9c400be1b4c8cb6992d9ba5f14dElliott Hughes        // to a local reference.
707de68817bdae0ca038d824ba79a70ac17cae405e6Elliott Hughes        return self->jniLocalRefTable.contains(obj) ? JNILocalRefType : JNIInvalidRefType;
708ea333384b92db9c400be1b4c8cb6992d9ba5f14dElliott Hughes    } else if (obj == kInvalidIndirectRefObject) {
7090423f0e813a3807168fe5524405eb96675532097Andy McFadden        return JNIInvalidRefType;
7100423f0e813a3807168fe5524405eb96675532097Andy McFadden    } else {
711ce0968340f9ddd54f20e38d4946bfd2ef8f1f343Elliott Hughes        return (jobjectRefType) indirectRefKind(jobj);
7120423f0e813a3807168fe5524405eb96675532097Andy McFadden    }
713f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
714f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
71523ba9600c0207ef406513fce4c0278796e0b9415Elliott Hughesstatic void dumpMethods(Method* methods, size_t methodCount, const char* name) {
71606bfe18dd51ecac0078201537ee373318553285bElliott Hughes    size_t i;
71706bfe18dd51ecac0078201537ee373318553285bElliott Hughes    for (i = 0; i < methodCount; ++i) {
71806bfe18dd51ecac0078201537ee373318553285bElliott Hughes        Method* method = &methods[i];
71906bfe18dd51ecac0078201537ee373318553285bElliott Hughes        if (strcmp(name, method->name) == 0) {
72006bfe18dd51ecac0078201537ee373318553285bElliott Hughes            char* desc = dexProtoCopyMethodDescriptor(&method->prototype);
721c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block            ALOGE("Candidate: %s.%s:%s", method->clazz->descriptor, name, desc);
72206bfe18dd51ecac0078201537ee373318553285bElliott Hughes            free(desc);
72306bfe18dd51ecac0078201537ee373318553285bElliott Hughes        }
72406bfe18dd51ecac0078201537ee373318553285bElliott Hughes    }
72506bfe18dd51ecac0078201537ee373318553285bElliott Hughes}
72606bfe18dd51ecac0078201537ee373318553285bElliott Hughes
72723ba9600c0207ef406513fce4c0278796e0b9415Elliott Hughesstatic void dumpCandidateMethods(ClassObject* clazz, const char* methodName, const char* signature) {
728c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block    ALOGE("ERROR: couldn't find native method");
729c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block    ALOGE("Requested: %s.%s:%s", clazz->descriptor, methodName, signature);
73006bfe18dd51ecac0078201537ee373318553285bElliott Hughes    dumpMethods(clazz->virtualMethods, clazz->virtualMethodCount, methodName);
73106bfe18dd51ecac0078201537ee373318553285bElliott Hughes    dumpMethods(clazz->directMethods, clazz->directMethodCount, methodName);
73206bfe18dd51ecac0078201537ee373318553285bElliott Hughes}
73306bfe18dd51ecac0078201537ee373318553285bElliott Hughes
734f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
735f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Register a method that uses JNI calling conventions.
736f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
737f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic bool dvmRegisterJNIMethod(ClassObject* clazz, const char* methodName,
738f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const char* signature, void* fnPtr)
739f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
74023ba9600c0207ef406513fce4c0278796e0b9415Elliott Hughes    if (fnPtr == NULL) {
74106bfe18dd51ecac0078201537ee373318553285bElliott Hughes        return false;
74223ba9600c0207ef406513fce4c0278796e0b9415Elliott Hughes    }
743f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
74465852761e37f938409b85a901a0fb1d98d361023Elliott Hughes    // If a signature starts with a '!', we take that as a sign that the native code doesn't
7458c8d1594ae9c7b588bb990e7407f4baa6185ecb9Elliott Hughes    // need the extra JNI arguments (the JNIEnv* and the jclass).
7461a87dec67db6c5a37442c1338d9b8c626c95a545Elliott Hughes    bool fastJni = false;
74765852761e37f938409b85a901a0fb1d98d361023Elliott Hughes    if (*signature == '!') {
7481a87dec67db6c5a37442c1338d9b8c626c95a545Elliott Hughes        fastJni = true;
74965852761e37f938409b85a901a0fb1d98d361023Elliott Hughes        ++signature;
75092c1f6f1b4249e4e379452ee7b49f027052bf4ceSteve Block        ALOGV("fast JNI method %s.%s:%s detected", clazz->descriptor, methodName, signature);
75165852761e37f938409b85a901a0fb1d98d361023Elliott Hughes    }
75265852761e37f938409b85a901a0fb1d98d361023Elliott Hughes
75323ba9600c0207ef406513fce4c0278796e0b9415Elliott Hughes    Method* method = dvmFindDirectMethodByDescriptor(clazz, methodName, signature);
75423ba9600c0207ef406513fce4c0278796e0b9415Elliott Hughes    if (method == NULL) {
755f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        method = dvmFindVirtualMethodByDescriptor(clazz, methodName, signature);
75623ba9600c0207ef406513fce4c0278796e0b9415Elliott Hughes    }
757f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (method == NULL) {
75806bfe18dd51ecac0078201537ee373318553285bElliott Hughes        dumpCandidateMethods(clazz, methodName, signature);
75906bfe18dd51ecac0078201537ee373318553285bElliott Hughes        return false;
760f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
761f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
762f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (!dvmIsNativeMethod(method)) {
763e8e1ddccd616e8226b7cc1e4e9fdb327429249e8Steve Block        ALOGW("Unable to register: not native: %s.%s:%s", clazz->descriptor, methodName, signature);
76406bfe18dd51ecac0078201537ee373318553285bElliott Hughes        return false;
765f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
766f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
7671a87dec67db6c5a37442c1338d9b8c626c95a545Elliott Hughes    if (fastJni) {
76865852761e37f938409b85a901a0fb1d98d361023Elliott Hughes        // In this case, we have extra constraints to check...
76965852761e37f938409b85a901a0fb1d98d361023Elliott Hughes        if (dvmIsSynchronizedMethod(method)) {
7708c8d1594ae9c7b588bb990e7407f4baa6185ecb9Elliott Hughes            // Synchronization is usually provided by the JNI bridge,
7718c8d1594ae9c7b588bb990e7407f4baa6185ecb9Elliott Hughes            // but we won't have one.
772c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block            ALOGE("fast JNI method %s.%s:%s cannot be synchronized",
77365852761e37f938409b85a901a0fb1d98d361023Elliott Hughes                    clazz->descriptor, methodName, signature);
77465852761e37f938409b85a901a0fb1d98d361023Elliott Hughes            return false;
77565852761e37f938409b85a901a0fb1d98d361023Elliott Hughes        }
77665852761e37f938409b85a901a0fb1d98d361023Elliott Hughes        if (!dvmIsStaticMethod(method)) {
7778c8d1594ae9c7b588bb990e7407f4baa6185ecb9Elliott Hughes            // There's no real reason for this constraint, but since we won't
7788c8d1594ae9c7b588bb990e7407f4baa6185ecb9Elliott Hughes            // be supplying a JNIEnv* or a jobject 'this', you're effectively
7798c8d1594ae9c7b588bb990e7407f4baa6185ecb9Elliott Hughes            // static anyway, so it seems clearer to say so.
780c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block            ALOGE("fast JNI method %s.%s:%s cannot be non-static",
78165852761e37f938409b85a901a0fb1d98d361023Elliott Hughes                    clazz->descriptor, methodName, signature);
78265852761e37f938409b85a901a0fb1d98d361023Elliott Hughes            return false;
78365852761e37f938409b85a901a0fb1d98d361023Elliott Hughes        }
78465852761e37f938409b85a901a0fb1d98d361023Elliott Hughes    }
78565852761e37f938409b85a901a0fb1d98d361023Elliott Hughes
786f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (method->nativeFunc != dvmResolveNativeMethod) {
7871e83b4d026199073c057edcb7836d06ae0716390Andy McFadden        /* this is allowed, but unusual */
78892c1f6f1b4249e4e379452ee7b49f027052bf4ceSteve Block        ALOGV("Note: %s.%s:%s was already registered", clazz->descriptor, methodName, signature);
789f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
790f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
7911a87dec67db6c5a37442c1338d9b8c626c95a545Elliott Hughes    method->fastJni = fastJni;
79259b6177e2fa9c9f1f16d7eff57e481f5282afbdaAndy McFadden    dvmUseJNIBridge(method, fnPtr);
793f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
79492c1f6f1b4249e4e379452ee7b49f027052bf4ceSteve Block    ALOGV("JNI-registered %s.%s:%s", clazz->descriptor, methodName, signature);
79506bfe18dd51ecac0078201537ee373318553285bElliott Hughes    return true;
796f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
797f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
7983f04fa049734772a945243d64d6ce9a34b39b730Elliott Hughesstatic const char* builtInPrefixes[] = {
7993f04fa049734772a945243d64d6ce9a34b39b730Elliott Hughes    "Landroid/",
8003f04fa049734772a945243d64d6ce9a34b39b730Elliott Hughes    "Lcom/android/",
8013f04fa049734772a945243d64d6ce9a34b39b730Elliott Hughes    "Lcom/google/android/",
8023f04fa049734772a945243d64d6ce9a34b39b730Elliott Hughes    "Ldalvik/",
8033f04fa049734772a945243d64d6ce9a34b39b730Elliott Hughes    "Ljava/",
8043f04fa049734772a945243d64d6ce9a34b39b730Elliott Hughes    "Ljavax/",
8053f04fa049734772a945243d64d6ce9a34b39b730Elliott Hughes    "Llibcore/",
8063f04fa049734772a945243d64d6ce9a34b39b730Elliott Hughes    "Lorg/apache/harmony/",
8073f04fa049734772a945243d64d6ce9a34b39b730Elliott Hughes};
808a6e94ff55517438569d207e3ed552c8c127bcac9Elliott Hughes
80923ba9600c0207ef406513fce4c0278796e0b9415Elliott Hughesstatic bool shouldTrace(Method* method) {
8103f04fa049734772a945243d64d6ce9a34b39b730Elliott Hughes    const char* className = method->clazz->descriptor;
8113f04fa049734772a945243d64d6ce9a34b39b730Elliott Hughes    // Return true if the -Xjnitrace setting implies we should trace 'method'.
8123f04fa049734772a945243d64d6ce9a34b39b730Elliott Hughes    if (gDvm.jniTrace && strstr(className, gDvm.jniTrace)) {
8133f04fa049734772a945243d64d6ce9a34b39b730Elliott Hughes        return true;
8143f04fa049734772a945243d64d6ce9a34b39b730Elliott Hughes    }
8153f04fa049734772a945243d64d6ce9a34b39b730Elliott Hughes    // Return true if we're trying to log all third-party JNI activity and 'method' doesn't look
8163f04fa049734772a945243d64d6ce9a34b39b730Elliott Hughes    // like part of Android.
8173f04fa049734772a945243d64d6ce9a34b39b730Elliott Hughes    if (gDvmJni.logThirdPartyJni) {
8183f04fa049734772a945243d64d6ce9a34b39b730Elliott Hughes        for (size_t i = 0; i < NELEM(builtInPrefixes); ++i) {
8193f04fa049734772a945243d64d6ce9a34b39b730Elliott Hughes            if (strstr(className, builtInPrefixes[i]) == className) {
8203f04fa049734772a945243d64d6ce9a34b39b730Elliott Hughes                return false;
8213f04fa049734772a945243d64d6ce9a34b39b730Elliott Hughes            }
8223f04fa049734772a945243d64d6ce9a34b39b730Elliott Hughes        }
8233f04fa049734772a945243d64d6ce9a34b39b730Elliott Hughes        return true;
8243f04fa049734772a945243d64d6ce9a34b39b730Elliott Hughes    }
8253f04fa049734772a945243d64d6ce9a34b39b730Elliott Hughes    return false;
826de66fcbc1d7fde20bdafb508b769028d8f2ec9bcElliott Hughes}
827de66fcbc1d7fde20bdafb508b769028d8f2ec9bcElliott Hughes
828de66fcbc1d7fde20bdafb508b769028d8f2ec9bcElliott Hughes/*
829de66fcbc1d7fde20bdafb508b769028d8f2ec9bcElliott Hughes * Point "method->nativeFunc" at the JNI bridge, and overload "method->insns"
830de66fcbc1d7fde20bdafb508b769028d8f2ec9bcElliott Hughes * to point at the actual function.
831de66fcbc1d7fde20bdafb508b769028d8f2ec9bcElliott Hughes */
83223ba9600c0207ef406513fce4c0278796e0b9415Elliott Hughesvoid dvmUseJNIBridge(Method* method, void* func) {
833a6e94ff55517438569d207e3ed552c8c127bcac9Elliott Hughes    method->shouldTrace = shouldTrace(method);
834a6e94ff55517438569d207e3ed552c8c127bcac9Elliott Hughes
835a6e94ff55517438569d207e3ed552c8c127bcac9Elliott Hughes    // Does the method take any reference arguments?
836a6e94ff55517438569d207e3ed552c8c127bcac9Elliott Hughes    method->noRef = true;
837a6e94ff55517438569d207e3ed552c8c127bcac9Elliott Hughes    const char* cp = method->shorty;
838a6e94ff55517438569d207e3ed552c8c127bcac9Elliott Hughes    while (*++cp != '\0') { // Pre-increment to skip return type.
839a6e94ff55517438569d207e3ed552c8c127bcac9Elliott Hughes        if (*cp == 'L') {
840a6e94ff55517438569d207e3ed552c8c127bcac9Elliott Hughes            method->noRef = false;
841a6e94ff55517438569d207e3ed552c8c127bcac9Elliott Hughes            break;
842a6e94ff55517438569d207e3ed552c8c127bcac9Elliott Hughes        }
843a6e94ff55517438569d207e3ed552c8c127bcac9Elliott Hughes    }
844a6e94ff55517438569d207e3ed552c8c127bcac9Elliott Hughes
845a6e94ff55517438569d207e3ed552c8c127bcac9Elliott Hughes    DalvikBridgeFunc bridge = gDvmJni.useCheckJni ? dvmCheckCallJNIMethod : dvmCallJNIMethod;
846a6e94ff55517438569d207e3ed552c8c127bcac9Elliott Hughes    dvmSetNativeFunc(method, bridge, (const u2*) func);
847a6e94ff55517438569d207e3ed552c8c127bcac9Elliott Hughes}
848a6e94ff55517438569d207e3ed552c8c127bcac9Elliott Hughes
849a6e94ff55517438569d207e3ed552c8c127bcac9Elliott Hughes// TODO: rewrite this to share code with CheckJNI's tracing...
850a6e94ff55517438569d207e3ed552c8c127bcac9Elliott Hughesstatic void appendValue(char type, const JValue value, char* buf, size_t n, bool appendComma)
851a6e94ff55517438569d207e3ed552c8c127bcac9Elliott Hughes{
852a6e94ff55517438569d207e3ed552c8c127bcac9Elliott Hughes    size_t len = strlen(buf);
853a6e94ff55517438569d207e3ed552c8c127bcac9Elliott Hughes    if (len >= n - 32) { // 32 should be longer than anything we could append.
854a6e94ff55517438569d207e3ed552c8c127bcac9Elliott Hughes        buf[len - 1] = '.';
855a6e94ff55517438569d207e3ed552c8c127bcac9Elliott Hughes        buf[len - 2] = '.';
856a6e94ff55517438569d207e3ed552c8c127bcac9Elliott Hughes        buf[len - 3] = '.';
857a6e94ff55517438569d207e3ed552c8c127bcac9Elliott Hughes        return;
858a6e94ff55517438569d207e3ed552c8c127bcac9Elliott Hughes    }
859a6e94ff55517438569d207e3ed552c8c127bcac9Elliott Hughes    char* p = buf + len;
860a6e94ff55517438569d207e3ed552c8c127bcac9Elliott Hughes    switch (type) {
861a6e94ff55517438569d207e3ed552c8c127bcac9Elliott Hughes    case 'B':
862a6e94ff55517438569d207e3ed552c8c127bcac9Elliott Hughes        if (value.b >= 0 && value.b < 10) {
863a6e94ff55517438569d207e3ed552c8c127bcac9Elliott Hughes            sprintf(p, "%d", value.b);
864a6e94ff55517438569d207e3ed552c8c127bcac9Elliott Hughes        } else {
865a6e94ff55517438569d207e3ed552c8c127bcac9Elliott Hughes            sprintf(p, "%#x (%d)", value.b, value.b);
866a6e94ff55517438569d207e3ed552c8c127bcac9Elliott Hughes        }
867a6e94ff55517438569d207e3ed552c8c127bcac9Elliott Hughes        break;
868a6e94ff55517438569d207e3ed552c8c127bcac9Elliott Hughes    case 'C':
869a6e94ff55517438569d207e3ed552c8c127bcac9Elliott Hughes        if (value.c < 0x7f && value.c >= ' ') {
870a6e94ff55517438569d207e3ed552c8c127bcac9Elliott Hughes            sprintf(p, "U+%x ('%c')", value.c, value.c);
871a6e94ff55517438569d207e3ed552c8c127bcac9Elliott Hughes        } else {
872a6e94ff55517438569d207e3ed552c8c127bcac9Elliott Hughes            sprintf(p, "U+%x", value.c);
873a6e94ff55517438569d207e3ed552c8c127bcac9Elliott Hughes        }
874a6e94ff55517438569d207e3ed552c8c127bcac9Elliott Hughes        break;
875a6e94ff55517438569d207e3ed552c8c127bcac9Elliott Hughes    case 'D':
876a6e94ff55517438569d207e3ed552c8c127bcac9Elliott Hughes        sprintf(p, "%g", value.d);
877a6e94ff55517438569d207e3ed552c8c127bcac9Elliott Hughes        break;
878a6e94ff55517438569d207e3ed552c8c127bcac9Elliott Hughes    case 'F':
879a6e94ff55517438569d207e3ed552c8c127bcac9Elliott Hughes        sprintf(p, "%g", value.f);
880a6e94ff55517438569d207e3ed552c8c127bcac9Elliott Hughes        break;
881a6e94ff55517438569d207e3ed552c8c127bcac9Elliott Hughes    case 'I':
882a6e94ff55517438569d207e3ed552c8c127bcac9Elliott Hughes        sprintf(p, "%d", value.i);
883a6e94ff55517438569d207e3ed552c8c127bcac9Elliott Hughes        break;
884a6e94ff55517438569d207e3ed552c8c127bcac9Elliott Hughes    case 'L':
885a6e94ff55517438569d207e3ed552c8c127bcac9Elliott Hughes        sprintf(p, "%#x", value.i);
886a6e94ff55517438569d207e3ed552c8c127bcac9Elliott Hughes        break;
887a6e94ff55517438569d207e3ed552c8c127bcac9Elliott Hughes    case 'J':
888a6e94ff55517438569d207e3ed552c8c127bcac9Elliott Hughes        sprintf(p, "%lld", value.j);
889a6e94ff55517438569d207e3ed552c8c127bcac9Elliott Hughes        break;
890a6e94ff55517438569d207e3ed552c8c127bcac9Elliott Hughes    case 'S':
891a6e94ff55517438569d207e3ed552c8c127bcac9Elliott Hughes        sprintf(p, "%d", value.s);
892a6e94ff55517438569d207e3ed552c8c127bcac9Elliott Hughes        break;
893a6e94ff55517438569d207e3ed552c8c127bcac9Elliott Hughes    case 'V':
894a6e94ff55517438569d207e3ed552c8c127bcac9Elliott Hughes        strcpy(p, "void");
895a6e94ff55517438569d207e3ed552c8c127bcac9Elliott Hughes        break;
896a6e94ff55517438569d207e3ed552c8c127bcac9Elliott Hughes    case 'Z':
897a6e94ff55517438569d207e3ed552c8c127bcac9Elliott Hughes        strcpy(p, value.z ? "true" : "false");
898a6e94ff55517438569d207e3ed552c8c127bcac9Elliott Hughes        break;
899a6e94ff55517438569d207e3ed552c8c127bcac9Elliott Hughes    default:
900a6e94ff55517438569d207e3ed552c8c127bcac9Elliott Hughes        sprintf(p, "unknown type '%c'", type);
901a6e94ff55517438569d207e3ed552c8c127bcac9Elliott Hughes        break;
902a6e94ff55517438569d207e3ed552c8c127bcac9Elliott Hughes    }
903a6e94ff55517438569d207e3ed552c8c127bcac9Elliott Hughes
904a6e94ff55517438569d207e3ed552c8c127bcac9Elliott Hughes    if (appendComma) {
905a6e94ff55517438569d207e3ed552c8c127bcac9Elliott Hughes        strcat(p, ", ");
906a6e94ff55517438569d207e3ed552c8c127bcac9Elliott Hughes    }
907a6e94ff55517438569d207e3ed552c8c127bcac9Elliott Hughes}
908a6e94ff55517438569d207e3ed552c8c127bcac9Elliott Hughes
909a6e94ff55517438569d207e3ed552c8c127bcac9Elliott Hughesstatic void logNativeMethodEntry(const Method* method, const u4* args)
910a6e94ff55517438569d207e3ed552c8c127bcac9Elliott Hughes{
911a6e94ff55517438569d207e3ed552c8c127bcac9Elliott Hughes    char thisString[32] = { 0 };
912a6e94ff55517438569d207e3ed552c8c127bcac9Elliott Hughes    const u4* sp = args;
913a6e94ff55517438569d207e3ed552c8c127bcac9Elliott Hughes    if (!dvmIsStaticMethod(method)) {
914a6e94ff55517438569d207e3ed552c8c127bcac9Elliott Hughes        sprintf(thisString, "this=0x%08x ", *sp++);
915a6e94ff55517438569d207e3ed552c8c127bcac9Elliott Hughes    }
916a6e94ff55517438569d207e3ed552c8c127bcac9Elliott Hughes
917a6e94ff55517438569d207e3ed552c8c127bcac9Elliott Hughes    char argsString[128]= { 0 };
918a6e94ff55517438569d207e3ed552c8c127bcac9Elliott Hughes    const char* desc = &method->shorty[1];
919a6e94ff55517438569d207e3ed552c8c127bcac9Elliott Hughes    while (*desc != '\0') {
920a6e94ff55517438569d207e3ed552c8c127bcac9Elliott Hughes        char argType = *desc++;
921a6e94ff55517438569d207e3ed552c8c127bcac9Elliott Hughes        JValue value;
922a6e94ff55517438569d207e3ed552c8c127bcac9Elliott Hughes        if (argType == 'D' || argType == 'J') {
923a6e94ff55517438569d207e3ed552c8c127bcac9Elliott Hughes            value.j = dvmGetArgLong(sp, 0);
924a6e94ff55517438569d207e3ed552c8c127bcac9Elliott Hughes            sp += 2;
925a6e94ff55517438569d207e3ed552c8c127bcac9Elliott Hughes        } else {
926a6e94ff55517438569d207e3ed552c8c127bcac9Elliott Hughes            value.i = *sp++;
927a6e94ff55517438569d207e3ed552c8c127bcac9Elliott Hughes        }
928a6e94ff55517438569d207e3ed552c8c127bcac9Elliott Hughes        appendValue(argType, value, argsString, sizeof(argsString),
929a6e94ff55517438569d207e3ed552c8c127bcac9Elliott Hughes        *desc != '\0');
930a6e94ff55517438569d207e3ed552c8c127bcac9Elliott Hughes    }
931a6e94ff55517438569d207e3ed552c8c127bcac9Elliott Hughes
932a6e94ff55517438569d207e3ed552c8c127bcac9Elliott Hughes    std::string className(dvmHumanReadableDescriptor(method->clazz->descriptor));
933a6e94ff55517438569d207e3ed552c8c127bcac9Elliott Hughes    char* signature = dexProtoCopyMethodDescriptor(&method->prototype);
9344308417beec548c2b2c06ecec4f7f4a965b09fb2Steve Block    ALOGI("-> %s %s%s %s(%s)", className.c_str(), method->name, signature, thisString, argsString);
935a6e94ff55517438569d207e3ed552c8c127bcac9Elliott Hughes    free(signature);
936a6e94ff55517438569d207e3ed552c8c127bcac9Elliott Hughes}
937a6e94ff55517438569d207e3ed552c8c127bcac9Elliott Hughes
938a6e94ff55517438569d207e3ed552c8c127bcac9Elliott Hughesstatic void logNativeMethodExit(const Method* method, Thread* self, const JValue returnValue)
939a6e94ff55517438569d207e3ed552c8c127bcac9Elliott Hughes{
940a6e94ff55517438569d207e3ed552c8c127bcac9Elliott Hughes    std::string className(dvmHumanReadableDescriptor(method->clazz->descriptor));
941a6e94ff55517438569d207e3ed552c8c127bcac9Elliott Hughes    char* signature = dexProtoCopyMethodDescriptor(&method->prototype);
942a6e94ff55517438569d207e3ed552c8c127bcac9Elliott Hughes    if (dvmCheckException(self)) {
943a6e94ff55517438569d207e3ed552c8c127bcac9Elliott Hughes        Object* exception = dvmGetException(self);
944a6e94ff55517438569d207e3ed552c8c127bcac9Elliott Hughes        std::string exceptionClassName(dvmHumanReadableDescriptor(exception->clazz->descriptor));
9454308417beec548c2b2c06ecec4f7f4a965b09fb2Steve Block        ALOGI("<- %s %s%s threw %s", className.c_str(),
946a6e94ff55517438569d207e3ed552c8c127bcac9Elliott Hughes                method->name, signature, exceptionClassName.c_str());
947a6e94ff55517438569d207e3ed552c8c127bcac9Elliott Hughes    } else {
948a6e94ff55517438569d207e3ed552c8c127bcac9Elliott Hughes        char returnValueString[128] = { 0 };
949a6e94ff55517438569d207e3ed552c8c127bcac9Elliott Hughes        char returnType = method->shorty[0];
950a6e94ff55517438569d207e3ed552c8c127bcac9Elliott Hughes        appendValue(returnType, returnValue, returnValueString, sizeof(returnValueString), false);
9514308417beec548c2b2c06ecec4f7f4a965b09fb2Steve Block        ALOGI("<- %s %s%s returned %s", className.c_str(),
952a6e94ff55517438569d207e3ed552c8c127bcac9Elliott Hughes                method->name, signature, returnValueString);
953a6e94ff55517438569d207e3ed552c8c127bcac9Elliott Hughes    }
954a6e94ff55517438569d207e3ed552c8c127bcac9Elliott Hughes    free(signature);
95559b6177e2fa9c9f1f16d7eff57e481f5282afbdaAndy McFadden}
95659b6177e2fa9c9f1f16d7eff57e481f5282afbdaAndy McFadden
95759b6177e2fa9c9f1f16d7eff57e481f5282afbdaAndy McFadden/*
958f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Get the method currently being executed by examining the interp stack.
959f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
96023ba9600c0207ef406513fce4c0278796e0b9415Elliott Hughesconst Method* dvmGetCurrentJNIMethod() {
961f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(dvmThreadSelf() != NULL);
962f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
96330bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee    void* fp = dvmThreadSelf()->interpSave.curFrame;
964f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const Method* meth = SAVEAREA_FROM_FP(fp)->method;
965f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
966f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(meth != NULL);
967f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(dvmIsNativeMethod(meth));
968f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return meth;
969f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
970f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
971f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
972f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Track a JNI MonitorEnter in the current thread.
973f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
974f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The goal is to be able to "implicitly" release all JNI-held monitors
975f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * when the thread detaches.
976f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
977f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Monitors may be entered multiple times, so we add a new entry for each
978f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * enter call.  It would be more efficient to keep a counter.  At present
979f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * there's no real motivation to improve this however.
980f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
98123ba9600c0207ef406513fce4c0278796e0b9415Elliott Hughesstatic void trackMonitorEnter(Thread* self, Object* obj) {
982f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    static const int kInitialSize = 16;
983f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ReferenceTable* refTable = &self->jniMonitorRefTable;
984f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
985f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* init table on first use */
986f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (refTable->table == NULL) {
987f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(refTable->maxEntries == 0);
988f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
989f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (!dvmInitReferenceTable(refTable, kInitialSize, INT_MAX)) {
990c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block            ALOGE("Unable to initialize monitor tracking table");
99185e8913705f23a5e799690134746219f64498f29Elliott Hughes            ReportJniError();
992f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
993f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
994f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
995f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (!dvmAddToReferenceTable(refTable, obj)) {
996f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* ran out of memory? could throw exception instead */
997c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block        ALOGE("Unable to add entry to monitor tracking table");
99885e8913705f23a5e799690134746219f64498f29Elliott Hughes        ReportJniError();
999f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
100023ba9600c0207ef406513fce4c0278796e0b9415Elliott Hughes        LOGVV("--- added monitor %p", obj);
1001f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1002f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1003f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1004f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1005f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Track a JNI MonitorExit in the current thread.
1006f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
100723ba9600c0207ef406513fce4c0278796e0b9415Elliott Hughesstatic void trackMonitorExit(Thread* self, Object* obj) {
1008ab00d455ea67fbf4090567bb09ead8017896ea61Andy McFadden    ReferenceTable* pRefTable = &self->jniMonitorRefTable;
1009f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1010ab00d455ea67fbf4090567bb09ead8017896ea61Andy McFadden    if (!dvmRemoveFromReferenceTable(pRefTable, pRefTable->table, obj)) {
1011c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block        ALOGE("JNI monitor %p not found in tracking list", obj);
1012f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* keep going? */
1013f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
101423ba9600c0207ef406513fce4c0278796e0b9415Elliott Hughes        LOGVV("--- removed monitor %p", obj);
1015f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1016f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1017f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1018f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1019f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Release all monitors held by the jniMonitorRefTable list.
1020f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
102123ba9600c0207ef406513fce4c0278796e0b9415Elliott Hughesvoid dvmReleaseJniMonitors(Thread* self) {
1022ab00d455ea67fbf4090567bb09ead8017896ea61Andy McFadden    ReferenceTable* pRefTable = &self->jniMonitorRefTable;
1023ab00d455ea67fbf4090567bb09ead8017896ea61Andy McFadden    Object** top = pRefTable->table;
1024f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
102523ba9600c0207ef406513fce4c0278796e0b9415Elliott Hughes    if (top == NULL) {
1026f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return;
102723ba9600c0207ef406513fce4c0278796e0b9415Elliott Hughes    }
1028ab00d455ea67fbf4090567bb09ead8017896ea61Andy McFadden    Object** ptr = pRefTable->nextEntry;
1029f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    while (--ptr >= top) {
1030f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (!dvmUnlockObject(self, *ptr)) {
1031e8e1ddccd616e8226b7cc1e4e9fdb327429249e8Steve Block            ALOGW("Unable to unlock monitor %p at thread detach", *ptr);
1032f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
103323ba9600c0207ef406513fce4c0278796e0b9415Elliott Hughes            LOGVV("--- detach-releasing monitor %p", *ptr);
1034f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1035f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1036f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1037f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* zap it */
1038ab00d455ea67fbf4090567bb09ead8017896ea61Andy McFadden    pRefTable->nextEntry = pRefTable->table;
1039f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1040f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1041b76594d71daec00e5947a5f6f14282f8f9edebe4Andy McFadden/*
1042b76594d71daec00e5947a5f6f14282f8f9edebe4Andy McFadden * Determine if the specified class can be instantiated from JNI.  This
1043b76594d71daec00e5947a5f6f14282f8f9edebe4Andy McFadden * is used by AllocObject / NewObject, which are documented as throwing
1044b76594d71daec00e5947a5f6f14282f8f9edebe4Andy McFadden * an exception for abstract and interface classes, and not accepting
1045b76594d71daec00e5947a5f6f14282f8f9edebe4Andy McFadden * array classes.  We also want to reject attempts to create new Class
1046b76594d71daec00e5947a5f6f14282f8f9edebe4Andy McFadden * objects, since only DefineClass should do that.
1047b76594d71daec00e5947a5f6f14282f8f9edebe4Andy McFadden */
104823ba9600c0207ef406513fce4c0278796e0b9415Elliott Hughesstatic bool canAllocClass(ClassObject* clazz) {
1049b76594d71daec00e5947a5f6f14282f8f9edebe4Andy McFadden    if (dvmIsAbstractClass(clazz) || dvmIsInterfaceClass(clazz)) {
1050b76594d71daec00e5947a5f6f14282f8f9edebe4Andy McFadden        /* JNI spec defines what this throws */
1051bc606f5e72b16f3759f5d414c7444204908718aaDan Bornstein        dvmThrowInstantiationException(clazz, "abstract class or interface");
1052b76594d71daec00e5947a5f6f14282f8f9edebe4Andy McFadden        return false;
1053c6d2470eec726ae0ad95e4fd2d9d7da7cb2cdcbaDan Bornstein    } else if (dvmIsArrayClass(clazz) || dvmIsTheClassClass(clazz)) {
1054b76594d71daec00e5947a5f6f14282f8f9edebe4Andy McFadden        /* spec says "must not" for arrays, ignores Class */
1055bc606f5e72b16f3759f5d414c7444204908718aaDan Bornstein        dvmThrowInstantiationException(clazz, "wrong JNI function");
1056b76594d71daec00e5947a5f6f14282f8f9edebe4Andy McFadden        return false;
1057b76594d71daec00e5947a5f6f14282f8f9edebe4Andy McFadden    }
1058b76594d71daec00e5947a5f6f14282f8f9edebe4Andy McFadden    return true;
1059b76594d71daec00e5947a5f6f14282f8f9edebe4Andy McFadden}
1060b76594d71daec00e5947a5f6f14282f8f9edebe4Andy McFadden
1061f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1062f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1063f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * ===========================================================================
1064d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden *      JNI call bridge
1065d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden * ===========================================================================
1066d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden */
1067d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden
1068d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden/*
1069d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden * The functions here form a bridge between interpreted code and JNI native
1070d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden * functions.  The basic task is to convert an array of primitives and
1071d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden * references into C-style function arguments.  This is architecture-specific
1072d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden * and usually requires help from assembly code.
1073d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden *
1074d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden * The bridge takes four arguments: the array of parameters, a place to
1075d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden * store the function result (if any), the method to call, and a pointer
1076d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden * to the current thread.
1077d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden *
1078d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden * These functions aren't called directly from elsewhere in the VM.
1079d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden * A pointer in the Method struct points to one of these, and when a native
1080d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden * method is invoked the interpreter jumps to it.
1081d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden *
1082d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden * (The "internal native" methods are invoked the same way, but instead
1083d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden * of calling through a bridge, the target method is called directly.)
1084d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden *
1085d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden * The "args" array should not be modified, but we do so anyway for
1086d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden * performance reasons.  We know that it points to the "outs" area on
1087d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden * the current method's interpreted stack.  This area is ignored by the
1088d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden * precise GC, because there is no register map for a native method (for
1089d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden * an interpreted method the args would be listed in the argument set).
1090d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden * We know all of the values exist elsewhere on the interpreted stack,
1091d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden * because the method call setup copies them right before making the call,
1092d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden * so we don't have to worry about concealing stuff from the GC.
1093d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden *
1094d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden * If we don't want to modify "args", we either have to create a local
1095d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden * copy and modify it before calling dvmPlatformInvoke, or we have to do
1096d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden * the local reference replacement within dvmPlatformInvoke.  The latter
1097d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden * has some performance advantages, though if we can inline the local
1098d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden * reference adds we may win when there's a lot of reference args (unless
1099d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden * we want to code up some local ref table manipulation in assembly.
1100d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden */
1101d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden
1102d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden/*
11030423f0e813a3807168fe5524405eb96675532097Andy McFadden * If necessary, convert the value in pResult from a local/global reference
11040423f0e813a3807168fe5524405eb96675532097Andy McFadden * to an object pointer.
1105c759b9f089e8e09df335a030d0555366d9395aebAndy McFadden *
1106c759b9f089e8e09df335a030d0555366d9395aebAndy McFadden * If the returned reference is invalid, kInvalidIndirectRefObject will
1107c759b9f089e8e09df335a030d0555366d9395aebAndy McFadden * be returned in pResult.
11080423f0e813a3807168fe5524405eb96675532097Andy McFadden */
11090423f0e813a3807168fe5524405eb96675532097Andy McFaddenstatic inline void convertReferenceResult(JNIEnv* env, JValue* pResult,
11100423f0e813a3807168fe5524405eb96675532097Andy McFadden    const Method* method, Thread* self)
11110423f0e813a3807168fe5524405eb96675532097Andy McFadden{
111223ba9600c0207ef406513fce4c0278796e0b9415Elliott Hughes    if (method->shorty[0] == 'L' && !dvmCheckException(self) && pResult->l != NULL) {
1113de68817bdae0ca038d824ba79a70ac17cae405e6Elliott Hughes        pResult->l = dvmDecodeIndirectRef(self, (jobject) pResult->l);
11140423f0e813a3807168fe5524405eb96675532097Andy McFadden    }
11150423f0e813a3807168fe5524405eb96675532097Andy McFadden}
11160423f0e813a3807168fe5524405eb96675532097Andy McFadden
11170423f0e813a3807168fe5524405eb96675532097Andy McFadden/*
1118d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden * General form, handles all cases.
1119d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden */
1120a6e94ff55517438569d207e3ed552c8c127bcac9Elliott Hughesvoid dvmCallJNIMethod(const u4* args, JValue* pResult, const Method* method, Thread* self) {
1121d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden    u4* modArgs = (u4*) args;
1122a6e94ff55517438569d207e3ed552c8c127bcac9Elliott Hughes    jclass staticMethodClass = NULL;
1123d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden
1124de68817bdae0ca038d824ba79a70ac17cae405e6Elliott Hughes    u4 accessFlags = method->accessFlags;
1125de68817bdae0ca038d824ba79a70ac17cae405e6Elliott Hughes    bool isSynchronized = (accessFlags & ACC_SYNCHRONIZED) != 0;
1126a6e94ff55517438569d207e3ed552c8c127bcac9Elliott Hughes
11274308417beec548c2b2c06ecec4f7f4a965b09fb2Steve Block    //ALOGI("JNI calling %p (%s.%s:%s):", method->insns,
1128d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden    //    method->clazz->descriptor, method->name, method->shorty);
1129d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden
1130d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden    /*
1131d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden     * Walk the argument list, creating local references for appropriate
1132d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden     * arguments.
1133d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden     */
1134d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden    int idx = 0;
1135de68817bdae0ca038d824ba79a70ac17cae405e6Elliott Hughes    Object* lockObj;
1136de68817bdae0ca038d824ba79a70ac17cae405e6Elliott Hughes    if ((accessFlags & ACC_STATIC) != 0) {
1137a6e94ff55517438569d207e3ed552c8c127bcac9Elliott Hughes        lockObj = (Object*) method->clazz;
1138d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden        /* add the class object we pass in */
1139de68817bdae0ca038d824ba79a70ac17cae405e6Elliott Hughes        staticMethodClass = (jclass) addLocalReference(self, (Object*) method->clazz);
1140d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden    } else {
1141a6e94ff55517438569d207e3ed552c8c127bcac9Elliott Hughes        lockObj = (Object*) args[0];
1142d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden        /* add "this" */
1143de68817bdae0ca038d824ba79a70ac17cae405e6Elliott Hughes        modArgs[idx++] = (u4) addLocalReference(self, (Object*) modArgs[0]);
1144d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden    }
1145d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden
1146a6e94ff55517438569d207e3ed552c8c127bcac9Elliott Hughes    if (!method->noRef) {
1147a6e94ff55517438569d207e3ed552c8c127bcac9Elliott Hughes        const char* shorty = &method->shorty[1];        /* skip return type */
1148a6e94ff55517438569d207e3ed552c8c127bcac9Elliott Hughes        while (*shorty != '\0') {
1149a6e94ff55517438569d207e3ed552c8c127bcac9Elliott Hughes            switch (*shorty++) {
1150a6e94ff55517438569d207e3ed552c8c127bcac9Elliott Hughes            case 'L':
11514308417beec548c2b2c06ecec4f7f4a965b09fb2Steve Block                //ALOGI("  local %d: 0x%08x", idx, modArgs[idx]);
1152a6e94ff55517438569d207e3ed552c8c127bcac9Elliott Hughes                if (modArgs[idx] != 0) {
1153de68817bdae0ca038d824ba79a70ac17cae405e6Elliott Hughes                    modArgs[idx] = (u4) addLocalReference(self, (Object*) modArgs[idx]);
1154d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden                }
1155a6e94ff55517438569d207e3ed552c8c127bcac9Elliott Hughes                break;
1156a6e94ff55517438569d207e3ed552c8c127bcac9Elliott Hughes            case 'D':
1157a6e94ff55517438569d207e3ed552c8c127bcac9Elliott Hughes            case 'J':
1158a6e94ff55517438569d207e3ed552c8c127bcac9Elliott Hughes                idx++;
1159a6e94ff55517438569d207e3ed552c8c127bcac9Elliott Hughes                break;
1160a6e94ff55517438569d207e3ed552c8c127bcac9Elliott Hughes            default:
1161a6e94ff55517438569d207e3ed552c8c127bcac9Elliott Hughes                /* Z B C S I -- do nothing */
1162a6e94ff55517438569d207e3ed552c8c127bcac9Elliott Hughes                break;
1163d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden            }
1164d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden            idx++;
1165d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden        }
1166a6e94ff55517438569d207e3ed552c8c127bcac9Elliott Hughes    }
1167d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden
1168de68817bdae0ca038d824ba79a70ac17cae405e6Elliott Hughes    if (UNLIKELY(method->shouldTrace)) {
1169a6e94ff55517438569d207e3ed552c8c127bcac9Elliott Hughes        logNativeMethodEntry(method, args);
1170a6e94ff55517438569d207e3ed552c8c127bcac9Elliott Hughes    }
1171de68817bdae0ca038d824ba79a70ac17cae405e6Elliott Hughes    if (UNLIKELY(isSynchronized)) {
1172a6e94ff55517438569d207e3ed552c8c127bcac9Elliott Hughes        dvmLockObject(self, lockObj);
1173d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden    }
1174d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden
11750647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    ThreadStatus oldStatus = dvmChangeStatus(self, THREAD_NATIVE);
1176d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden
11771e83b4d026199073c057edcb7836d06ae0716390Andy McFadden    ANDROID_MEMBAR_FULL();      /* guarantee ordering on method->insns */
11781e83b4d026199073c057edcb7836d06ae0716390Andy McFadden    assert(method->insns != NULL);
11791e83b4d026199073c057edcb7836d06ae0716390Andy McFadden
1180de68817bdae0ca038d824ba79a70ac17cae405e6Elliott Hughes    JNIEnv* env = self->jniEnv;
1181d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden    COMPUTE_STACK_SUM(self);
1182de68817bdae0ca038d824ba79a70ac17cae405e6Elliott Hughes    dvmPlatformInvoke(env,
1183a6e94ff55517438569d207e3ed552c8c127bcac9Elliott Hughes            (ClassObject*) staticMethodClass,
118465852761e37f938409b85a901a0fb1d98d361023Elliott Hughes            method->jniArgInfo, method->insSize, modArgs, method->shorty,
1185a6e94ff55517438569d207e3ed552c8c127bcac9Elliott Hughes            (void*) method->insns, pResult);
1186d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden    CHECK_STACK_SUM(self);
1187d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden
1188d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden    dvmChangeStatus(self, oldStatus);
11890423f0e813a3807168fe5524405eb96675532097Andy McFadden
11900423f0e813a3807168fe5524405eb96675532097Andy McFadden    convertReferenceResult(env, pResult, method, self);
1191d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden
1192de68817bdae0ca038d824ba79a70ac17cae405e6Elliott Hughes    if (UNLIKELY(isSynchronized)) {
1193a6e94ff55517438569d207e3ed552c8c127bcac9Elliott Hughes        dvmUnlockObject(self, lockObj);
1194d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden    }
1195de68817bdae0ca038d824ba79a70ac17cae405e6Elliott Hughes    if (UNLIKELY(method->shouldTrace)) {
1196a6e94ff55517438569d207e3ed552c8c127bcac9Elliott Hughes        logNativeMethodExit(method, self, *pResult);
1197d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden    }
1198d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden}
1199d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden
1200d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden/*
1201d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden * ===========================================================================
1202f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *      JNI implementation
1203f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * ===========================================================================
1204f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1205f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1206f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1207f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Return the version of the native method interface.
1208f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
120923ba9600c0207ef406513fce4c0278796e0b9415Elliott Hughesstatic jint GetVersion(JNIEnv* env) {
1210f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
1211f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * There is absolutely no need to toggle the mode for correct behavior.
1212f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * However, it does provide native code with a simple "suspend self
1213f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * if necessary" call.
1214f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
12150647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    ScopedJniThreadState ts(env);
1216f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return JNI_VERSION_1_6;
1217f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1218f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1219f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1220f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Create a new class from a bag of bytes.
1221f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1222f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This is not currently supported within Dalvik.
1223f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1224f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic jclass DefineClass(JNIEnv* env, const char *name, jobject loader,
1225f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const jbyte* buf, jsize bufLen)
1226f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1227f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    UNUSED_PARAMETER(name);
1228f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    UNUSED_PARAMETER(loader);
1229f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    UNUSED_PARAMETER(buf);
1230f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    UNUSED_PARAMETER(bufLen);
1231f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
12320647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    ScopedJniThreadState ts(env);
1233e8e1ddccd616e8226b7cc1e4e9fdb327429249e8Steve Block    ALOGW("JNI DefineClass is not supported");
1234f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return NULL;
1235f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1236f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1237f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1238f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Find a class by name.
1239f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1240f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We have to use the "no init" version of FindClass here, because we might
1241f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * be getting the class prior to registering native methods that will be
1242f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * used in <clinit>.
1243f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1244f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We need to get the class loader associated with the current native
1245f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * method.  If there is no native method, e.g. we're calling this from native
1246f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * code right after creating the VM, the spec says we need to use the class
1247f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * loader returned by "ClassLoader.getBaseClassLoader".  There is no such
1248f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * method, but it's likely they meant ClassLoader.getSystemClassLoader.
1249f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We can't get that until after the VM has initialized though.
1250f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
125123ba9600c0207ef406513fce4c0278796e0b9415Elliott Hughesstatic jclass FindClass(JNIEnv* env, const char* name) {
12520647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    ScopedJniThreadState ts(env);
1253f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
125489383030aca8f77aeab73540404ba332ce5ac035Elliott Hughes    const Method* thisMethod = dvmGetCurrentJNIMethod();
1255f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(thisMethod != NULL);
1256f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
125789383030aca8f77aeab73540404ba332ce5ac035Elliott Hughes    Object* loader;
125889383030aca8f77aeab73540404ba332ce5ac035Elliott Hughes    Object* trackedLoader = NULL;
12590647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    if (ts.self()->classLoaderOverride != NULL) {
1260f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* hack for JNI_OnLoad */
1261f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(strcmp(thisMethod->name, "nativeLoad") == 0);
12620647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes        loader = ts.self()->classLoaderOverride;
126300feda9a6a12b3a894fbe10876636973d2a03ac2Carl Shapiro    } else if (thisMethod == gDvm.methDalvikSystemNativeStart_main ||
126400feda9a6a12b3a894fbe10876636973d2a03ac2Carl Shapiro               thisMethod == gDvm.methDalvikSystemNativeStart_run) {
1265f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* start point of invocation interface */
126689383030aca8f77aeab73540404ba332ce5ac035Elliott Hughes        if (!gDvm.initializing) {
126750cab51bb381c5da01adfd61954ddca37607f51eAndy McFadden            loader = trackedLoader = dvmGetSystemClassLoader();
126889383030aca8f77aeab73540404ba332ce5ac035Elliott Hughes        } else {
1269f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            loader = NULL;
127089383030aca8f77aeab73540404ba332ce5ac035Elliott Hughes        }
1271f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
1272f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        loader = thisMethod->clazz->classLoader;
1273f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1274f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
127589383030aca8f77aeab73540404ba332ce5ac035Elliott Hughes    char* descriptor = dvmNameToDescriptor(name);
127689383030aca8f77aeab73540404ba332ce5ac035Elliott Hughes    if (descriptor == NULL) {
127789383030aca8f77aeab73540404ba332ce5ac035Elliott Hughes        return NULL;
127889383030aca8f77aeab73540404ba332ce5ac035Elliott Hughes    }
127989383030aca8f77aeab73540404ba332ce5ac035Elliott Hughes    ClassObject* clazz = dvmFindClassNoInit(descriptor, loader);
128089383030aca8f77aeab73540404ba332ce5ac035Elliott Hughes    free(descriptor);
1281f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1282de68817bdae0ca038d824ba79a70ac17cae405e6Elliott Hughes    jclass jclazz = (jclass) addLocalReference(ts.self(), (Object*) clazz);
12830647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    dvmReleaseTrackedAlloc(trackedLoader, ts.self());
1284ab00d455ea67fbf4090567bb09ead8017896ea61Andy McFadden    return jclazz;
1285f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1286f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1287f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1288f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Return the superclass of a class.
1289f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
129023ba9600c0207ef406513fce4c0278796e0b9415Elliott Hughesstatic jclass GetSuperclass(JNIEnv* env, jclass jclazz) {
12910647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    ScopedJniThreadState ts(env);
1292de68817bdae0ca038d824ba79a70ac17cae405e6Elliott Hughes    ClassObject* clazz = (ClassObject*) dvmDecodeIndirectRef(ts.self(), jclazz);
1293de68817bdae0ca038d824ba79a70ac17cae405e6Elliott Hughes    return (jclass) addLocalReference(ts.self(), (Object*)clazz->super);
1294f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1295f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1296f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1297f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Determine whether an object of clazz1 can be safely cast to clazz2.
1298f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1299f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Like IsInstanceOf, but with a pair of class objects instead of obj+class.
1300f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
130123ba9600c0207ef406513fce4c0278796e0b9415Elliott Hughesstatic jboolean IsAssignableFrom(JNIEnv* env, jclass jclazz1, jclass jclazz2) {
13020647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    ScopedJniThreadState ts(env);
1303de68817bdae0ca038d824ba79a70ac17cae405e6Elliott Hughes    ClassObject* clazz1 = (ClassObject*) dvmDecodeIndirectRef(ts.self(), jclazz1);
1304de68817bdae0ca038d824ba79a70ac17cae405e6Elliott Hughes    ClassObject* clazz2 = (ClassObject*) dvmDecodeIndirectRef(ts.self(), jclazz2);
13050647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    return dvmInstanceof(clazz1, clazz2);
1306f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1307f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1308f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1309f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Given a java.lang.reflect.Method or .Constructor, return a methodID.
1310f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
131123ba9600c0207ef406513fce4c0278796e0b9415Elliott Hughesstatic jmethodID FromReflectedMethod(JNIEnv* env, jobject jmethod) {
13120647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    ScopedJniThreadState ts(env);
1313de68817bdae0ca038d824ba79a70ac17cae405e6Elliott Hughes    Object* method = dvmDecodeIndirectRef(ts.self(), jmethod);
13140647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    return (jmethodID) dvmGetMethodFromReflectObj(method);
1315f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1316f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1317f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1318f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Given a java.lang.reflect.Field, return a fieldID.
1319f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
132023ba9600c0207ef406513fce4c0278796e0b9415Elliott Hughesstatic jfieldID FromReflectedField(JNIEnv* env, jobject jfield) {
13210647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    ScopedJniThreadState ts(env);
1322de68817bdae0ca038d824ba79a70ac17cae405e6Elliott Hughes    Object* field = dvmDecodeIndirectRef(ts.self(), jfield);
13230647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    return (jfieldID) dvmGetFieldFromReflectObj(field);
1324f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1325f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1326f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1327f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Convert a methodID to a java.lang.reflect.Method or .Constructor.
1328f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1329f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * (The "isStatic" field does not appear in the spec.)
1330f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1331f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Throws OutOfMemory and returns NULL on failure.
1332f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
133323ba9600c0207ef406513fce4c0278796e0b9415Elliott Hughesstatic jobject ToReflectedMethod(JNIEnv* env, jclass jcls, jmethodID methodID, jboolean isStatic) {
13340647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    ScopedJniThreadState ts(env);
1335de68817bdae0ca038d824ba79a70ac17cae405e6Elliott Hughes    ClassObject* clazz = (ClassObject*) dvmDecodeIndirectRef(ts.self(), jcls);
1336ab00d455ea67fbf4090567bb09ead8017896ea61Andy McFadden    Object* obj = dvmCreateReflectObjForMethod(clazz, (Method*) methodID);
1337f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmReleaseTrackedAlloc(obj, NULL);
1338de68817bdae0ca038d824ba79a70ac17cae405e6Elliott Hughes    return addLocalReference(ts.self(), obj);
1339f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1340f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1341f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1342f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Convert a fieldID to a java.lang.reflect.Field.
1343f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1344f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * (The "isStatic" field does not appear in the spec.)
1345f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1346f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Throws OutOfMemory and returns NULL on failure.
1347f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
134823ba9600c0207ef406513fce4c0278796e0b9415Elliott Hughesstatic jobject ToReflectedField(JNIEnv* env, jclass jcls, jfieldID fieldID, jboolean isStatic) {
13490647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    ScopedJniThreadState ts(env);
1350de68817bdae0ca038d824ba79a70ac17cae405e6Elliott Hughes    ClassObject* clazz = (ClassObject*) dvmDecodeIndirectRef(ts.self(), jcls);
1351e3c01dac83e6eea7f82fe81ed89cfbdd9791dbc9Carl Shapiro    Object* obj = dvmCreateReflectObjForField(clazz, (Field*) fieldID);
1352f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmReleaseTrackedAlloc(obj, NULL);
1353de68817bdae0ca038d824ba79a70ac17cae405e6Elliott Hughes    return addLocalReference(ts.self(), obj);
1354f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1355f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1356f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1357f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Take this exception and throw it.
1358f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
135923ba9600c0207ef406513fce4c0278796e0b9415Elliott Hughesstatic jint Throw(JNIEnv* env, jthrowable jobj) {
13600647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    ScopedJniThreadState ts(env);
1361ab00d455ea67fbf4090567bb09ead8017896ea61Andy McFadden    if (jobj != NULL) {
1362de68817bdae0ca038d824ba79a70ac17cae405e6Elliott Hughes        Object* obj = dvmDecodeIndirectRef(ts.self(), jobj);
13630647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes        dvmSetException(ts.self(), obj);
13640647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes        return JNI_OK;
1365ab00d455ea67fbf4090567bb09ead8017896ea61Andy McFadden    }
13660647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    return JNI_ERR;
1367f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1368f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1369f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1370ab00d455ea67fbf4090567bb09ead8017896ea61Andy McFadden * Constructs an exception object from the specified class with the message
1371f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * specified by "message", and throws it.
1372f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
137323ba9600c0207ef406513fce4c0278796e0b9415Elliott Hughesstatic jint ThrowNew(JNIEnv* env, jclass jclazz, const char* message) {
13740647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    ScopedJniThreadState ts(env);
1375de68817bdae0ca038d824ba79a70ac17cae405e6Elliott Hughes    ClassObject* clazz = (ClassObject*) dvmDecodeIndirectRef(ts.self(), jclazz);
13760b8b293f228b3d341054bc1fad8a92d6e533b4ddDan Bornstein    dvmThrowException(clazz, message);
1377ab00d455ea67fbf4090567bb09ead8017896ea61Andy McFadden    // TODO: should return failure if this didn't work (e.g. OOM)
1378f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return JNI_OK;
1379f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1380f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1381f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1382f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * If an exception is being thrown, return the exception object.  Otherwise,
1383f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * return NULL.
1384f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1385f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * TODO: if there is no pending exception, we should be able to skip the
1386f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * enter/exit checks.  If we find one, we need to enter and then re-fetch
1387f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the exception (in case it got moved by a compacting GC).
1388f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
138923ba9600c0207ef406513fce4c0278796e0b9415Elliott Hughesstatic jthrowable ExceptionOccurred(JNIEnv* env) {
13900647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    ScopedJniThreadState ts(env);
13910647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    Object* exception = dvmGetException(ts.self());
1392de68817bdae0ca038d824ba79a70ac17cae405e6Elliott Hughes    jthrowable localException = (jthrowable) addLocalReference(ts.self(), exception);
1393f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (localException == NULL && exception != NULL) {
1394f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
1395f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * We were unable to add a new local reference, and threw a new
1396f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * exception.  We can't return "exception", because it's not a
1397f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * local reference.  So we have to return NULL, indicating that
1398f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * there was no exception, even though it's pretty much raining
1399f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * exceptions in here.
1400f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
1401e8e1ddccd616e8226b7cc1e4e9fdb327429249e8Steve Block        ALOGW("JNI WARNING: addLocal/exception combo");
1402f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1403f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return localException;
1404f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1405f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1406f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1407f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Print an exception and stack trace to stderr.
1408f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
140923ba9600c0207ef406513fce4c0278796e0b9415Elliott Hughesstatic void ExceptionDescribe(JNIEnv* env) {
14100647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    ScopedJniThreadState ts(env);
14110647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    Object* exception = dvmGetException(ts.self());
1412f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (exception != NULL) {
1413f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmPrintExceptionStackTrace();
1414f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
14154308417beec548c2b2c06ecec4f7f4a965b09fb2Steve Block        ALOGI("Odd: ExceptionDescribe called, but no exception pending");
1416f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1417f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1418f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1419f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1420f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Clear the exception currently being thrown.
1421f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1422f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * TODO: we should be able to skip the enter/exit stuff.
1423f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
142423ba9600c0207ef406513fce4c0278796e0b9415Elliott Hughesstatic void ExceptionClear(JNIEnv* env) {
14250647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    ScopedJniThreadState ts(env);
14260647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    dvmClearException(ts.self());
1427f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1428f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1429f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1430f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Kill the VM.  This function does not return.
1431f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
143223ba9600c0207ef406513fce4c0278796e0b9415Elliott Hughesstatic void FatalError(JNIEnv* env, const char* msg) {
1433f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    //dvmChangeStatus(NULL, THREAD_RUNNING);
1434c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block    ALOGE("JNI posting fatal error: %s", msg);
143585e8913705f23a5e799690134746219f64498f29Elliott Hughes    ReportJniError();
1436f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1437f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1438f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1439f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Push a new JNI frame on the stack, with a new set of locals.
1440f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1441f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The new frame must have the same method pointer.  (If for no other
1442f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * reason than FindClass needs it to get the appropriate class loader.)
1443f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
144423ba9600c0207ef406513fce4c0278796e0b9415Elliott Hughesstatic jint PushLocalFrame(JNIEnv* env, jint capacity) {
14450647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    ScopedJniThreadState ts(env);
1446de68817bdae0ca038d824ba79a70ac17cae405e6Elliott Hughes    if (!ensureLocalCapacity(ts.self(), capacity) ||
14470647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes            !dvmPushLocalFrame(ts.self(), dvmGetCurrentJNIMethod()))
1448f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    {
1449f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* yes, OutOfMemoryError, not StackOverflowError */
14500647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes        dvmClearException(ts.self());
1451d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein        dvmThrowOutOfMemoryError("out of stack in JNI PushLocalFrame");
14520647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes        return JNI_ERR;
1453f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
14540647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    return JNI_OK;
1455f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1456f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1457f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1458fec4890b3ad9acd581d2c13664dc96cde38f10e7Andy McFadden * Pop the local frame off.  If "jresult" is not null, add it as a
1459f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * local reference on the now-current frame.
1460f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
146123ba9600c0207ef406513fce4c0278796e0b9415Elliott Hughesstatic jobject PopLocalFrame(JNIEnv* env, jobject jresult) {
14620647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    ScopedJniThreadState ts(env);
1463de68817bdae0ca038d824ba79a70ac17cae405e6Elliott Hughes    Object* result = dvmDecodeIndirectRef(ts.self(), jresult);
14640647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    if (!dvmPopLocalFrame(ts.self())) {
1465e8e1ddccd616e8226b7cc1e4e9fdb327429249e8Steve Block        ALOGW("JNI WARNING: too many PopLocalFrame calls");
14660647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes        dvmClearException(ts.self());
1467d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein        dvmThrowRuntimeException("too many PopLocalFrame calls");
1468f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1469de68817bdae0ca038d824ba79a70ac17cae405e6Elliott Hughes    return addLocalReference(ts.self(), result);
1470f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1471f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1472f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1473f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Add a reference to the global list.
1474f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
147523ba9600c0207ef406513fce4c0278796e0b9415Elliott Hughesstatic jobject NewGlobalRef(JNIEnv* env, jobject jobj) {
14760647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    ScopedJniThreadState ts(env);
1477de68817bdae0ca038d824ba79a70ac17cae405e6Elliott Hughes    Object* obj = dvmDecodeIndirectRef(ts.self(), jobj);
14780647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    return addGlobalReference(obj);
1479f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1480f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1481f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1482f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Delete a reference from the global list.
1483f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
148423ba9600c0207ef406513fce4c0278796e0b9415Elliott Hughesstatic void DeleteGlobalRef(JNIEnv* env, jobject jglobalRef) {
14850647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    ScopedJniThreadState ts(env);
1486ab00d455ea67fbf4090567bb09ead8017896ea61Andy McFadden    deleteGlobalReference(jglobalRef);
1487f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1488f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1489f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1490f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1491f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Add a reference to the local list.
1492f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
149323ba9600c0207ef406513fce4c0278796e0b9415Elliott Hughesstatic jobject NewLocalRef(JNIEnv* env, jobject jobj) {
14940647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    ScopedJniThreadState ts(env);
1495de68817bdae0ca038d824ba79a70ac17cae405e6Elliott Hughes    Object* obj = dvmDecodeIndirectRef(ts.self(), jobj);
1496de68817bdae0ca038d824ba79a70ac17cae405e6Elliott Hughes    return addLocalReference(ts.self(), obj);
1497f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1498f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1499f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1500f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Delete a reference from the local list.
1501f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
150223ba9600c0207ef406513fce4c0278796e0b9415Elliott Hughesstatic void DeleteLocalRef(JNIEnv* env, jobject jlocalRef) {
15030647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    ScopedJniThreadState ts(env);
1504de68817bdae0ca038d824ba79a70ac17cae405e6Elliott Hughes    deleteLocalReference(ts.self(), jlocalRef);
1505f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1506f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1507f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1508f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Ensure that the local references table can hold at least this many
1509f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * references.
1510f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
151123ba9600c0207ef406513fce4c0278796e0b9415Elliott Hughesstatic jint EnsureLocalCapacity(JNIEnv* env, jint capacity) {
15120647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    ScopedJniThreadState ts(env);
1513de68817bdae0ca038d824ba79a70ac17cae405e6Elliott Hughes    bool okay = ensureLocalCapacity(ts.self(), capacity);
1514f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (!okay) {
1515d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein        dvmThrowOutOfMemoryError("can't ensure local reference capacity");
1516f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
15170647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    return okay ? 0 : -1;
1518f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1519f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1520f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1521f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1522f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Determine whether two Object references refer to the same underlying object.
1523f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
152423ba9600c0207ef406513fce4c0278796e0b9415Elliott Hughesstatic jboolean IsSameObject(JNIEnv* env, jobject jref1, jobject jref2) {
15250647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    ScopedJniThreadState ts(env);
1526de68817bdae0ca038d824ba79a70ac17cae405e6Elliott Hughes    Object* obj1 = dvmDecodeIndirectRef(ts.self(), jref1);
1527de68817bdae0ca038d824ba79a70ac17cae405e6Elliott Hughes    Object* obj2 = dvmDecodeIndirectRef(ts.self(), jref2);
15280647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    return (obj1 == obj2);
1529f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1530f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1531f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1532f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Allocate a new object without invoking any constructors.
1533f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
153423ba9600c0207ef406513fce4c0278796e0b9415Elliott Hughesstatic jobject AllocObject(JNIEnv* env, jclass jclazz) {
15350647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    ScopedJniThreadState ts(env);
1536f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1537de68817bdae0ca038d824ba79a70ac17cae405e6Elliott Hughes    ClassObject* clazz = (ClassObject*) dvmDecodeIndirectRef(ts.self(), jclazz);
1538b76594d71daec00e5947a5f6f14282f8f9edebe4Andy McFadden    if (!canAllocClass(clazz) ||
1539b76594d71daec00e5947a5f6f14282f8f9edebe4Andy McFadden        (!dvmIsClassInitialized(clazz) && !dvmInitClass(clazz)))
1540b76594d71daec00e5947a5f6f14282f8f9edebe4Andy McFadden    {
15410647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes        assert(dvmCheckException(ts.self()));
15420647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes        return NULL;
1543f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1544f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
15450647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    Object* newObj = dvmAllocObject(clazz, ALLOC_DONT_TRACK);
1546de68817bdae0ca038d824ba79a70ac17cae405e6Elliott Hughes    return addLocalReference(ts.self(), newObj);
1547f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1548f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1549f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1550ab00d455ea67fbf4090567bb09ead8017896ea61Andy McFadden * Allocate a new object and invoke the supplied constructor.
1551f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
155223ba9600c0207ef406513fce4c0278796e0b9415Elliott Hughesstatic jobject NewObject(JNIEnv* env, jclass jclazz, jmethodID methodID, ...) {
15530647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    ScopedJniThreadState ts(env);
1554de68817bdae0ca038d824ba79a70ac17cae405e6Elliott Hughes    ClassObject* clazz = (ClassObject*) dvmDecodeIndirectRef(ts.self(), jclazz);
1555f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
155623ba9600c0207ef406513fce4c0278796e0b9415Elliott Hughes    if (!canAllocClass(clazz) || (!dvmIsClassInitialized(clazz) && !dvmInitClass(clazz))) {
15570647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes        assert(dvmCheckException(ts.self()));
15580647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes        return NULL;
1559f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1560f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
15610647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    Object* newObj = dvmAllocObject(clazz, ALLOC_DONT_TRACK);
1562de68817bdae0ca038d824ba79a70ac17cae405e6Elliott Hughes    jobject result = addLocalReference(ts.self(), newObj);
15630647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    if (newObj != NULL) {
15640647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes        JValue unused;
15650647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes        va_list args;
15660647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes        va_start(args, methodID);
15670647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes        dvmCallMethodV(ts.self(), (Method*) methodID, newObj, true, &unused, args);
15680647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes        va_end(args);
15690647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    }
1570ab00d455ea67fbf4090567bb09ead8017896ea61Andy McFadden    return result;
1571f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
157223ba9600c0207ef406513fce4c0278796e0b9415Elliott Hughes
157323ba9600c0207ef406513fce4c0278796e0b9415Elliott Hughesstatic jobject NewObjectV(JNIEnv* env, jclass jclazz, jmethodID methodID, va_list args) {
15740647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    ScopedJniThreadState ts(env);
1575de68817bdae0ca038d824ba79a70ac17cae405e6Elliott Hughes    ClassObject* clazz = (ClassObject*) dvmDecodeIndirectRef(ts.self(), jclazz);
1576f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
157723ba9600c0207ef406513fce4c0278796e0b9415Elliott Hughes    if (!canAllocClass(clazz) || (!dvmIsClassInitialized(clazz) && !dvmInitClass(clazz))) {
15780647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes        assert(dvmCheckException(ts.self()));
15790647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes        return NULL;
1580f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1581f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
15820647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    Object* newObj = dvmAllocObject(clazz, ALLOC_DONT_TRACK);
1583de68817bdae0ca038d824ba79a70ac17cae405e6Elliott Hughes    jobject result = addLocalReference(ts.self(), newObj);
15840647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    if (newObj != NULL) {
15850647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes        JValue unused;
15860647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes        dvmCallMethodV(ts.self(), (Method*) methodID, newObj, true, &unused, args);
15870647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    }
1588ab00d455ea67fbf4090567bb09ead8017896ea61Andy McFadden    return result;
1589f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
159023ba9600c0207ef406513fce4c0278796e0b9415Elliott Hughes
159123ba9600c0207ef406513fce4c0278796e0b9415Elliott Hughesstatic jobject NewObjectA(JNIEnv* env, jclass jclazz, jmethodID methodID, jvalue* args) {
15920647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    ScopedJniThreadState ts(env);
1593de68817bdae0ca038d824ba79a70ac17cae405e6Elliott Hughes    ClassObject* clazz = (ClassObject*) dvmDecodeIndirectRef(ts.self(), jclazz);
1594f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
159523ba9600c0207ef406513fce4c0278796e0b9415Elliott Hughes    if (!canAllocClass(clazz) || (!dvmIsClassInitialized(clazz) && !dvmInitClass(clazz))) {
15960647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes        assert(dvmCheckException(ts.self()));
15970647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes        return NULL;
1598f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1599f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
16000647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    Object* newObj = dvmAllocObject(clazz, ALLOC_DONT_TRACK);
1601de68817bdae0ca038d824ba79a70ac17cae405e6Elliott Hughes    jobject result = addLocalReference(ts.self(), newObj);
16020647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    if (newObj != NULL) {
16030647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes        JValue unused;
16040647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes        dvmCallMethodA(ts.self(), (Method*) methodID, newObj, true, &unused, args);
16050647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    }
1606ab00d455ea67fbf4090567bb09ead8017896ea61Andy McFadden    return result;
1607f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1608f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1609f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1610f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns the class of an object.
1611f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1612f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * JNI spec says: obj must not be NULL.
1613f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
161423ba9600c0207ef406513fce4c0278796e0b9415Elliott Hughesstatic jclass GetObjectClass(JNIEnv* env, jobject jobj) {
16150647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    ScopedJniThreadState ts(env);
1616f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1617ab00d455ea67fbf4090567bb09ead8017896ea61Andy McFadden    assert(jobj != NULL);
1618f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1619de68817bdae0ca038d824ba79a70ac17cae405e6Elliott Hughes    Object* obj = dvmDecodeIndirectRef(ts.self(), jobj);
1620de68817bdae0ca038d824ba79a70ac17cae405e6Elliott Hughes    return (jclass) addLocalReference(ts.self(), (Object*) obj->clazz);
1621f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1622f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1623f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1624f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Determine whether "obj" is an instance of "clazz".
1625f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
162623ba9600c0207ef406513fce4c0278796e0b9415Elliott Hughesstatic jboolean IsInstanceOf(JNIEnv* env, jobject jobj, jclass jclazz) {
16270647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    ScopedJniThreadState ts(env);
1628f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1629ab00d455ea67fbf4090567bb09ead8017896ea61Andy McFadden    assert(jclazz != NULL);
1630ab00d455ea67fbf4090567bb09ead8017896ea61Andy McFadden    if (jobj == NULL) {
16310647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes        return true;
1632ab00d455ea67fbf4090567bb09ead8017896ea61Andy McFadden    }
1633f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1634de68817bdae0ca038d824ba79a70ac17cae405e6Elliott Hughes    Object* obj = dvmDecodeIndirectRef(ts.self(), jobj);
1635de68817bdae0ca038d824ba79a70ac17cae405e6Elliott Hughes    ClassObject* clazz = (ClassObject*) dvmDecodeIndirectRef(ts.self(), jclazz);
16360647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    return dvmInstanceof(obj->clazz, clazz);
1637f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1638f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1639f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1640f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Get a method ID for an instance method.
1641f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1642da7334a4ba1bbffe40d3838f463565af46e716d9Andy McFadden * While Dalvik bytecode has distinct instructions for virtual, super,
1643da7334a4ba1bbffe40d3838f463565af46e716d9Andy McFadden * static, direct, and interface method invocation, JNI only provides
1644da7334a4ba1bbffe40d3838f463565af46e716d9Andy McFadden * two functions for acquiring a method ID.  This call handles everything
1645da7334a4ba1bbffe40d3838f463565af46e716d9Andy McFadden * but static methods.
1646da7334a4ba1bbffe40d3838f463565af46e716d9Andy McFadden *
1647f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * JNI defines <init> as an instance method, but Dalvik considers it a
1648f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * "direct" method, so we have to special-case it here.
1649f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1650f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Dalvik also puts all private methods into the "direct" list, so we
1651f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * really need to just search both lists.
1652f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
165323ba9600c0207ef406513fce4c0278796e0b9415Elliott Hughesstatic jmethodID GetMethodID(JNIEnv* env, jclass jclazz, const char* name, const char* sig) {
16540647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    ScopedJniThreadState ts(env);
1655f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1656de68817bdae0ca038d824ba79a70ac17cae405e6Elliott Hughes    ClassObject* clazz = (ClassObject*) dvmDecodeIndirectRef(ts.self(), jclazz);
1657f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (!dvmIsClassInitialized(clazz) && !dvmInitClass(clazz)) {
16580647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes        assert(dvmCheckException(ts.self()));
1659da7334a4ba1bbffe40d3838f463565af46e716d9Andy McFadden    } else if (dvmIsInterfaceClass(clazz)) {
1660da7334a4ba1bbffe40d3838f463565af46e716d9Andy McFadden        Method* meth = dvmFindInterfaceMethodHierByDescriptor(clazz, name, sig);
1661da7334a4ba1bbffe40d3838f463565af46e716d9Andy McFadden        if (meth == NULL) {
16620b8b293f228b3d341054bc1fad8a92d6e533b4ddDan Bornstein            dvmThrowExceptionFmt(gDvm.exNoSuchMethodError,
1663da7334a4ba1bbffe40d3838f463565af46e716d9Andy McFadden                "no method with name='%s' signature='%s' in interface %s",
1664da7334a4ba1bbffe40d3838f463565af46e716d9Andy McFadden                name, sig, clazz->descriptor);
1665da7334a4ba1bbffe40d3838f463565af46e716d9Andy McFadden        }
16660647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes        return (jmethodID) meth;
16670647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    }
16680647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    Method* meth = dvmFindVirtualMethodHierByDescriptor(clazz, name, sig);
16690647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    if (meth == NULL) {
16700647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes        /* search private methods and constructors; non-hierarchical */
16710647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes        meth = dvmFindDirectMethodByDescriptor(clazz, name, sig);
16720647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    }
16730647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    if (meth != NULL && dvmIsStaticMethod(meth)) {
1674062bf509a77fce9dfcb7e7b2e401cf2a124d83d5Steve Block        IF_ALOGD() {
16750647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes            char* desc = dexProtoCopyMethodDescriptor(&meth->prototype);
1676062bf509a77fce9dfcb7e7b2e401cf2a124d83d5Steve Block            ALOGD("GetMethodID: not returning static method %s.%s %s",
1677f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    clazz->descriptor, meth->name, desc);
16780647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes            free(desc);
1679f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
16800647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes        meth = NULL;
16810647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    }
16820647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    if (meth == NULL) {
16830647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes        dvmThrowExceptionFmt(gDvm.exNoSuchMethodError,
1684be9b0ebb8aaea25214331c70a0f6310b0678a112Andy McFadden                "no method with name='%s' signature='%s' in class %s",
1685be9b0ebb8aaea25214331c70a0f6310b0678a112Andy McFadden                name, sig, clazz->descriptor);
16860647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    } else {
16870647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes        /*
16880647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes         * The method's class may not be the same as clazz, but if
16890647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes         * it isn't this must be a virtual method and the class must
16900647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes         * be a superclass (and, hence, already initialized).
16910647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes         */
16920647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes        assert(dvmIsClassInitialized(meth->clazz) || dvmIsClassInitializing(meth->clazz));
1693f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
16940647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    return (jmethodID) meth;
1695f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1696f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1697f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1698f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Get a field ID (instance fields).
1699f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
170023ba9600c0207ef406513fce4c0278796e0b9415Elliott Hughesstatic jfieldID GetFieldID(JNIEnv* env, jclass jclazz, const char* name, const char* sig) {
17010647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    ScopedJniThreadState ts(env);
1702f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1703de68817bdae0ca038d824ba79a70ac17cae405e6Elliott Hughes    ClassObject* clazz = (ClassObject*) dvmDecodeIndirectRef(ts.self(), jclazz);
1704f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1705f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (!dvmIsClassInitialized(clazz) && !dvmInitClass(clazz)) {
17060647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes        assert(dvmCheckException(ts.self()));
17070647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes        return NULL;
17080647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    }
17090647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes
17100647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    jfieldID id = (jfieldID) dvmFindInstanceFieldHier(clazz, name, sig);
17110647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    if (id == NULL) {
17120647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes        dvmThrowExceptionFmt(gDvm.exNoSuchFieldError,
1713be9b0ebb8aaea25214331c70a0f6310b0678a112Andy McFadden                "no field with name='%s' signature='%s' in class %s",
1714be9b0ebb8aaea25214331c70a0f6310b0678a112Andy McFadden                name, sig, clazz->descriptor);
1715f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1716f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return id;
1717f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1718f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1719f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1720f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Get the method ID for a static method in a class.
1721f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
172223ba9600c0207ef406513fce4c0278796e0b9415Elliott Hughesstatic jmethodID GetStaticMethodID(JNIEnv* env, jclass jclazz, const char* name, const char* sig) {
17230647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    ScopedJniThreadState ts(env);
1724f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1725de68817bdae0ca038d824ba79a70ac17cae405e6Elliott Hughes    ClassObject* clazz = (ClassObject*) dvmDecodeIndirectRef(ts.self(), jclazz);
1726f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (!dvmIsClassInitialized(clazz) && !dvmInitClass(clazz)) {
17270647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes        assert(dvmCheckException(ts.self()));
17280647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes        return NULL;
17290647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    }
1730f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
17310647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    Method* meth = dvmFindDirectMethodHierByDescriptor(clazz, name, sig);
1732f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
17330647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    /* make sure it's static, not virtual+private */
17340647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    if (meth != NULL && !dvmIsStaticMethod(meth)) {
1735062bf509a77fce9dfcb7e7b2e401cf2a124d83d5Steve Block        IF_ALOGD() {
17360647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes            char* desc = dexProtoCopyMethodDescriptor(&meth->prototype);
1737062bf509a77fce9dfcb7e7b2e401cf2a124d83d5Steve Block            ALOGD("GetStaticMethodID: not returning nonstatic method %s.%s %s",
1738f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    clazz->descriptor, meth->name, desc);
17390647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes            free(desc);
1740f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
17410647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes        meth = NULL;
17420647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    }
1743f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
17440647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    jmethodID id = (jmethodID) meth;
17450647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    if (id == NULL) {
17460647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes        dvmThrowExceptionFmt(gDvm.exNoSuchMethodError,
1747be9b0ebb8aaea25214331c70a0f6310b0678a112Andy McFadden                "no static method with name='%s' signature='%s' in class %s",
1748be9b0ebb8aaea25214331c70a0f6310b0678a112Andy McFadden                name, sig, clazz->descriptor);
1749f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1750f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return id;
1751f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1752f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1753f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1754f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Get a field ID (static fields).
1755f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
175623ba9600c0207ef406513fce4c0278796e0b9415Elliott Hughesstatic jfieldID GetStaticFieldID(JNIEnv* env, jclass jclazz, const char* name, const char* sig) {
17570647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    ScopedJniThreadState ts(env);
1758f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1759de68817bdae0ca038d824ba79a70ac17cae405e6Elliott Hughes    ClassObject* clazz = (ClassObject*) dvmDecodeIndirectRef(ts.self(), jclazz);
1760f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (!dvmIsClassInitialized(clazz) && !dvmInitClass(clazz)) {
17610647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes        assert(dvmCheckException(ts.self()));
17620647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes        return NULL;
17630647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    }
17640647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes
17650647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    jfieldID id = (jfieldID) dvmFindStaticFieldHier(clazz, name, sig);
17660647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    if (id == NULL) {
17670647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes        dvmThrowExceptionFmt(gDvm.exNoSuchFieldError,
1768be9b0ebb8aaea25214331c70a0f6310b0678a112Andy McFadden                "no static field with name='%s' signature='%s' in class %s",
1769be9b0ebb8aaea25214331c70a0f6310b0678a112Andy McFadden                name, sig, clazz->descriptor);
1770f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1771f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return id;
1772f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1773f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1774f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1775f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Get a static field.
1776f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1777f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * If we get an object reference, add it to the local refs list.
1778f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1779f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#define GET_STATIC_TYPE_FIELD(_ctype, _jname, _isref)                       \
1780ab00d455ea67fbf4090567bb09ead8017896ea61Andy McFadden    static _ctype GetStatic##_jname##Field(JNIEnv* env, jclass jclazz,      \
1781f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        jfieldID fieldID)                                                   \
1782f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    {                                                                       \
1783ab00d455ea67fbf4090567bb09ead8017896ea61Andy McFadden        UNUSED_PARAMETER(jclazz);                                           \
17840647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes        ScopedJniThreadState ts(env);                                       \
1785f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        StaticField* sfield = (StaticField*) fieldID;                       \
1786ab00d455ea67fbf4090567bb09ead8017896ea61Andy McFadden        _ctype value;                                                       \
1787a7323974309c3b81cfe342db635d0bf30f36ff62Carl Shapiro        if (dvmIsVolatileField(sfield)) {                                   \
17889197746491686dd774d556d28a82c5b6e0ff7b09Andy McFadden            if (_isref) {   /* only when _ctype==jobject */                 \
17899197746491686dd774d556d28a82c5b6e0ff7b09Andy McFadden                Object* obj = dvmGetStaticFieldObjectVolatile(sfield);      \
1790de68817bdae0ca038d824ba79a70ac17cae405e6Elliott Hughes                value = (_ctype)(u4)addLocalReference(ts.self(), obj);            \
17919197746491686dd774d556d28a82c5b6e0ff7b09Andy McFadden            } else {                                                        \
17920647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes                value = (_ctype) dvmGetStaticField##_jname##Volatile(sfield);\
17939197746491686dd774d556d28a82c5b6e0ff7b09Andy McFadden            }                                                               \
1794ab00d455ea67fbf4090567bb09ead8017896ea61Andy McFadden        } else {                                                            \
17959197746491686dd774d556d28a82c5b6e0ff7b09Andy McFadden            if (_isref) {                                                   \
17969197746491686dd774d556d28a82c5b6e0ff7b09Andy McFadden                Object* obj = dvmGetStaticFieldObject(sfield);              \
1797de68817bdae0ca038d824ba79a70ac17cae405e6Elliott Hughes                value = (_ctype)(u4)addLocalReference(ts.self(), obj);            \
17989197746491686dd774d556d28a82c5b6e0ff7b09Andy McFadden            } else {                                                        \
17990647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes                value = (_ctype) dvmGetStaticField##_jname(sfield);         \
18009197746491686dd774d556d28a82c5b6e0ff7b09Andy McFadden            }                                                               \
1801ab00d455ea67fbf4090567bb09ead8017896ea61Andy McFadden        }                                                                   \
1802f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return value;                                                       \
1803f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1804f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectGET_STATIC_TYPE_FIELD(jobject, Object, true);
1805f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectGET_STATIC_TYPE_FIELD(jboolean, Boolean, false);
1806f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectGET_STATIC_TYPE_FIELD(jbyte, Byte, false);
1807f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectGET_STATIC_TYPE_FIELD(jchar, Char, false);
1808f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectGET_STATIC_TYPE_FIELD(jshort, Short, false);
1809f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectGET_STATIC_TYPE_FIELD(jint, Int, false);
1810f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectGET_STATIC_TYPE_FIELD(jlong, Long, false);
1811f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectGET_STATIC_TYPE_FIELD(jfloat, Float, false);
1812f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectGET_STATIC_TYPE_FIELD(jdouble, Double, false);
1813f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1814f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1815f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Set a static field.
1816f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1817fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro#define SET_STATIC_TYPE_FIELD(_ctype, _ctype2, _jname, _isref)              \
1818ab00d455ea67fbf4090567bb09ead8017896ea61Andy McFadden    static void SetStatic##_jname##Field(JNIEnv* env, jclass jclazz,        \
1819f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        jfieldID fieldID, _ctype value)                                     \
1820f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    {                                                                       \
1821ab00d455ea67fbf4090567bb09ead8017896ea61Andy McFadden        UNUSED_PARAMETER(jclazz);                                           \
18220647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes        ScopedJniThreadState ts(env);                                       \
1823f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        StaticField* sfield = (StaticField*) fieldID;                       \
1824a7323974309c3b81cfe342db635d0bf30f36ff62Carl Shapiro        if (dvmIsVolatileField(sfield)) {                                   \
18259197746491686dd774d556d28a82c5b6e0ff7b09Andy McFadden            if (_isref) {   /* only when _ctype==jobject */                 \
1826de68817bdae0ca038d824ba79a70ac17cae405e6Elliott Hughes                Object* valObj = dvmDecodeIndirectRef(ts.self(), (jobject)(u4)value); \
18279197746491686dd774d556d28a82c5b6e0ff7b09Andy McFadden                dvmSetStaticFieldObjectVolatile(sfield, valObj);            \
18289197746491686dd774d556d28a82c5b6e0ff7b09Andy McFadden            } else {                                                        \
1829fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro                dvmSetStaticField##_jname##Volatile(sfield, (_ctype2)value);\
18309197746491686dd774d556d28a82c5b6e0ff7b09Andy McFadden            }                                                               \
1831ab00d455ea67fbf4090567bb09ead8017896ea61Andy McFadden        } else {                                                            \
18329197746491686dd774d556d28a82c5b6e0ff7b09Andy McFadden            if (_isref) {                                                   \
1833de68817bdae0ca038d824ba79a70ac17cae405e6Elliott Hughes                Object* valObj = dvmDecodeIndirectRef(ts.self(), (jobject)(u4)value); \
18349197746491686dd774d556d28a82c5b6e0ff7b09Andy McFadden                dvmSetStaticFieldObject(sfield, valObj);                    \
18359197746491686dd774d556d28a82c5b6e0ff7b09Andy McFadden            } else {                                                        \
1836fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro                dvmSetStaticField##_jname(sfield, (_ctype2)value);          \
18379197746491686dd774d556d28a82c5b6e0ff7b09Andy McFadden            }                                                               \
1838ab00d455ea67fbf4090567bb09ead8017896ea61Andy McFadden        }                                                                   \
1839f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1840fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl ShapiroSET_STATIC_TYPE_FIELD(jobject, Object*, Object, true);
1841fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl ShapiroSET_STATIC_TYPE_FIELD(jboolean, bool, Boolean, false);
1842fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl ShapiroSET_STATIC_TYPE_FIELD(jbyte, s1, Byte, false);
1843fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl ShapiroSET_STATIC_TYPE_FIELD(jchar, u2, Char, false);
1844fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl ShapiroSET_STATIC_TYPE_FIELD(jshort, s2, Short, false);
1845fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl ShapiroSET_STATIC_TYPE_FIELD(jint, s4, Int, false);
1846fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl ShapiroSET_STATIC_TYPE_FIELD(jlong, s8, Long, false);
1847fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl ShapiroSET_STATIC_TYPE_FIELD(jfloat, float, Float, false);
1848fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl ShapiroSET_STATIC_TYPE_FIELD(jdouble, double, Double, false);
1849f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1850f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1851f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Get an instance field.
1852f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1853f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * If we get an object reference, add it to the local refs list.
1854f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1855f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#define GET_TYPE_FIELD(_ctype, _jname, _isref)                              \
1856ab00d455ea67fbf4090567bb09ead8017896ea61Andy McFadden    static _ctype Get##_jname##Field(JNIEnv* env, jobject jobj,             \
1857f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        jfieldID fieldID)                                                   \
1858f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    {                                                                       \
18590647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes        ScopedJniThreadState ts(env);                                       \
1860de68817bdae0ca038d824ba79a70ac17cae405e6Elliott Hughes        Object* obj = dvmDecodeIndirectRef(ts.self(), jobj);                      \
1861f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        InstField* field = (InstField*) fieldID;                            \
1862ab00d455ea67fbf4090567bb09ead8017896ea61Andy McFadden        _ctype value;                                                       \
1863a7323974309c3b81cfe342db635d0bf30f36ff62Carl Shapiro        if (dvmIsVolatileField(field)) {                            \
18649197746491686dd774d556d28a82c5b6e0ff7b09Andy McFadden            if (_isref) {   /* only when _ctype==jobject */                 \
18659197746491686dd774d556d28a82c5b6e0ff7b09Andy McFadden                Object* valObj =                                            \
18669197746491686dd774d556d28a82c5b6e0ff7b09Andy McFadden                    dvmGetFieldObjectVolatile(obj, field->byteOffset);      \
1867de68817bdae0ca038d824ba79a70ac17cae405e6Elliott Hughes                value = (_ctype)(u4)addLocalReference(ts.self(), valObj);         \
18689197746491686dd774d556d28a82c5b6e0ff7b09Andy McFadden            } else {                                                        \
18690647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes                value = (_ctype)                                            \
18709197746491686dd774d556d28a82c5b6e0ff7b09Andy McFadden                    dvmGetField##_jname##Volatile(obj, field->byteOffset);  \
18719197746491686dd774d556d28a82c5b6e0ff7b09Andy McFadden            }                                                               \
1872ab00d455ea67fbf4090567bb09ead8017896ea61Andy McFadden        } else {                                                            \
18739197746491686dd774d556d28a82c5b6e0ff7b09Andy McFadden            if (_isref) {                                                   \
18749197746491686dd774d556d28a82c5b6e0ff7b09Andy McFadden                Object* valObj = dvmGetFieldObject(obj, field->byteOffset); \
1875de68817bdae0ca038d824ba79a70ac17cae405e6Elliott Hughes                value = (_ctype)(u4)addLocalReference(ts.self(), valObj);         \
18769197746491686dd774d556d28a82c5b6e0ff7b09Andy McFadden            } else {                                                        \
18770647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes                value = (_ctype) dvmGetField##_jname(obj, field->byteOffset);\
18789197746491686dd774d556d28a82c5b6e0ff7b09Andy McFadden            }                                                               \
1879ab00d455ea67fbf4090567bb09ead8017896ea61Andy McFadden        }                                                                   \
1880f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return value;                                                       \
1881f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1882f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectGET_TYPE_FIELD(jobject, Object, true);
1883f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectGET_TYPE_FIELD(jboolean, Boolean, false);
1884f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectGET_TYPE_FIELD(jbyte, Byte, false);
1885f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectGET_TYPE_FIELD(jchar, Char, false);
1886f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectGET_TYPE_FIELD(jshort, Short, false);
1887f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectGET_TYPE_FIELD(jint, Int, false);
1888f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectGET_TYPE_FIELD(jlong, Long, false);
1889f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectGET_TYPE_FIELD(jfloat, Float, false);
1890f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectGET_TYPE_FIELD(jdouble, Double, false);
1891f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1892f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1893f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Set an instance field.
1894f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1895fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro#define SET_TYPE_FIELD(_ctype, _ctype2, _jname, _isref)                     \
1896ab00d455ea67fbf4090567bb09ead8017896ea61Andy McFadden    static void Set##_jname##Field(JNIEnv* env, jobject jobj,               \
1897f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        jfieldID fieldID, _ctype value)                                     \
1898f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    {                                                                       \
18990647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes        ScopedJniThreadState ts(env);                                       \
1900de68817bdae0ca038d824ba79a70ac17cae405e6Elliott Hughes        Object* obj = dvmDecodeIndirectRef(ts.self(), jobj); \
1901f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        InstField* field = (InstField*) fieldID;                            \
1902a7323974309c3b81cfe342db635d0bf30f36ff62Carl Shapiro        if (dvmIsVolatileField(field)) {                                    \
19039197746491686dd774d556d28a82c5b6e0ff7b09Andy McFadden            if (_isref) {   /* only when _ctype==jobject */                 \
1904de68817bdae0ca038d824ba79a70ac17cae405e6Elliott Hughes                Object* valObj = dvmDecodeIndirectRef(ts.self(), (jobject)(u4)value); \
19059197746491686dd774d556d28a82c5b6e0ff7b09Andy McFadden                dvmSetFieldObjectVolatile(obj, field->byteOffset, valObj);  \
19069197746491686dd774d556d28a82c5b6e0ff7b09Andy McFadden            } else {                                                        \
19079197746491686dd774d556d28a82c5b6e0ff7b09Andy McFadden                dvmSetField##_jname##Volatile(obj,                          \
1908fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro                    field->byteOffset, (_ctype2)value);                     \
19099197746491686dd774d556d28a82c5b6e0ff7b09Andy McFadden            }                                                               \
1910ab00d455ea67fbf4090567bb09ead8017896ea61Andy McFadden        } else {                                                            \
19119197746491686dd774d556d28a82c5b6e0ff7b09Andy McFadden            if (_isref) {                                                   \
1912de68817bdae0ca038d824ba79a70ac17cae405e6Elliott Hughes                Object* valObj = dvmDecodeIndirectRef(ts.self(), (jobject)(u4)value); \
19139197746491686dd774d556d28a82c5b6e0ff7b09Andy McFadden                dvmSetFieldObject(obj, field->byteOffset, valObj);          \
19149197746491686dd774d556d28a82c5b6e0ff7b09Andy McFadden            } else {                                                        \
1915fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro                dvmSetField##_jname(obj,                                    \
1916fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro                    field->byteOffset, (_ctype2)value);                     \
19179197746491686dd774d556d28a82c5b6e0ff7b09Andy McFadden            }                                                               \
1918ab00d455ea67fbf4090567bb09ead8017896ea61Andy McFadden        }                                                                   \
1919f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1920fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl ShapiroSET_TYPE_FIELD(jobject, Object*, Object, true);
1921fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl ShapiroSET_TYPE_FIELD(jboolean, bool, Boolean, false);
1922fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl ShapiroSET_TYPE_FIELD(jbyte, s1, Byte, false);
1923fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl ShapiroSET_TYPE_FIELD(jchar, u2, Char, false);
1924fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl ShapiroSET_TYPE_FIELD(jshort, s2, Short, false);
1925fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl ShapiroSET_TYPE_FIELD(jint, s4, Int, false);
1926fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl ShapiroSET_TYPE_FIELD(jlong, s8, Long, false);
1927fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl ShapiroSET_TYPE_FIELD(jfloat, float, Float, false);
1928fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl ShapiroSET_TYPE_FIELD(jdouble, double, Double, false);
1929f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1930f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1931f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Make a virtual method call.
1932f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1933f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Three versions (..., va_list, jvalue[]) for each return type.  If we're
1934f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * returning an Object, we have to add it to the local references table.
1935f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1936f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#define CALL_VIRTUAL(_ctype, _jname, _retfail, _retok, _isref)              \
1937ab00d455ea67fbf4090567bb09ead8017896ea61Andy McFadden    static _ctype Call##_jname##Method(JNIEnv* env, jobject jobj,           \
1938f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        jmethodID methodID, ...)                                            \
1939f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    {                                                                       \
19400647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes        ScopedJniThreadState ts(env);                                       \
1941de68817bdae0ca038d824ba79a70ac17cae405e6Elliott Hughes        Object* obj = dvmDecodeIndirectRef(ts.self(), jobj);                      \
1942f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        const Method* meth;                                                 \
1943f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        va_list args;                                                       \
1944f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        JValue result;                                                      \
1945ab00d455ea67fbf4090567bb09ead8017896ea61Andy McFadden        meth = dvmGetVirtualizedMethod(obj->clazz, (Method*)methodID);      \
1946f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (meth == NULL) {                                                 \
1947f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return _retfail;                                                \
1948f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }                                                                   \
1949f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        va_start(args, methodID);                                           \
19500647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes        dvmCallMethodV(ts.self(), meth, obj, true, &result, args);          \
1951f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        va_end(args);                                                       \
19520647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes        if (_isref && !dvmCheckException(ts.self()))                        \
1953de68817bdae0ca038d824ba79a70ac17cae405e6Elliott Hughes            result.l = (Object*)addLocalReference(ts.self(), result.l);           \
1954f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return _retok;                                                      \
1955f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }                                                                       \
1956ab00d455ea67fbf4090567bb09ead8017896ea61Andy McFadden    static _ctype Call##_jname##MethodV(JNIEnv* env, jobject jobj,          \
1957f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        jmethodID methodID, va_list args)                                   \
1958f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    {                                                                       \
19590647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes        ScopedJniThreadState ts(env);                                       \
1960de68817bdae0ca038d824ba79a70ac17cae405e6Elliott Hughes        Object* obj = dvmDecodeIndirectRef(ts.self(), jobj);                      \
1961f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        const Method* meth;                                                 \
1962f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        JValue result;                                                      \
1963ab00d455ea67fbf4090567bb09ead8017896ea61Andy McFadden        meth = dvmGetVirtualizedMethod(obj->clazz, (Method*)methodID);      \
1964f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (meth == NULL) {                                                 \
1965f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return _retfail;                                                \
1966f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }                                                                   \
19670647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes        dvmCallMethodV(ts.self(), meth, obj, true, &result, args);          \
19680647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes        if (_isref && !dvmCheckException(ts.self()))                        \
1969de68817bdae0ca038d824ba79a70ac17cae405e6Elliott Hughes            result.l = (Object*)addLocalReference(ts.self(), result.l);           \
1970f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return _retok;                                                      \
1971f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }                                                                       \
1972ab00d455ea67fbf4090567bb09ead8017896ea61Andy McFadden    static _ctype Call##_jname##MethodA(JNIEnv* env, jobject jobj,          \
1973f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        jmethodID methodID, jvalue* args)                                   \
1974f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    {                                                                       \
19750647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes        ScopedJniThreadState ts(env);                                       \
1976de68817bdae0ca038d824ba79a70ac17cae405e6Elliott Hughes        Object* obj = dvmDecodeIndirectRef(ts.self(), jobj);                      \
1977f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        const Method* meth;                                                 \
1978f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        JValue result;                                                      \
1979ab00d455ea67fbf4090567bb09ead8017896ea61Andy McFadden        meth = dvmGetVirtualizedMethod(obj->clazz, (Method*)methodID);      \
1980f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (meth == NULL) {                                                 \
1981f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return _retfail;                                                \
1982f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }                                                                   \
19830647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes        dvmCallMethodA(ts.self(), meth, obj, true, &result, args);          \
19840647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes        if (_isref && !dvmCheckException(ts.self()))                        \
1985de68817bdae0ca038d824ba79a70ac17cae405e6Elliott Hughes            result.l = (Object*)addLocalReference(ts.self(), result.l);           \
1986f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return _retok;                                                      \
1987f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
19880647d294bab9312be67a9032adfa4f0b9ba0984aElliott HughesCALL_VIRTUAL(jobject, Object, NULL, (jobject) result.l, true);
1989f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectCALL_VIRTUAL(jboolean, Boolean, 0, result.z, false);
1990f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectCALL_VIRTUAL(jbyte, Byte, 0, result.b, false);
1991f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectCALL_VIRTUAL(jchar, Char, 0, result.c, false);
1992f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectCALL_VIRTUAL(jshort, Short, 0, result.s, false);
1993f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectCALL_VIRTUAL(jint, Int, 0, result.i, false);
1994f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectCALL_VIRTUAL(jlong, Long, 0, result.j, false);
1995f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectCALL_VIRTUAL(jfloat, Float, 0.0f, result.f, false);
1996f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectCALL_VIRTUAL(jdouble, Double, 0.0, result.d, false);
1997f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectCALL_VIRTUAL(void, Void, , , false);
1998f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1999f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
2000f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Make a "non-virtual" method call.  We're still calling a virtual method,
2001f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * but this time we're not doing an indirection through the object's vtable.
2002f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The "clazz" parameter defines which implementation of a method we want.
2003f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
2004f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Three versions (..., va_list, jvalue[]) for each return type.
2005f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
2006f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#define CALL_NONVIRTUAL(_ctype, _jname, _retfail, _retok, _isref)           \
2007ab00d455ea67fbf4090567bb09ead8017896ea61Andy McFadden    static _ctype CallNonvirtual##_jname##Method(JNIEnv* env, jobject jobj, \
2008ab00d455ea67fbf4090567bb09ead8017896ea61Andy McFadden        jclass jclazz, jmethodID methodID, ...)                             \
2009f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    {                                                                       \
20100647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes        ScopedJniThreadState ts(env);                                       \
2011de68817bdae0ca038d824ba79a70ac17cae405e6Elliott Hughes        Object* obj = dvmDecodeIndirectRef(ts.self(), jobj);                      \
2012de68817bdae0ca038d824ba79a70ac17cae405e6Elliott Hughes        ClassObject* clazz = (ClassObject*) dvmDecodeIndirectRef(ts.self(), jclazz); \
2013f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        const Method* meth;                                                 \
2014f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        va_list args;                                                       \
2015f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        JValue result;                                                      \
2016ab00d455ea67fbf4090567bb09ead8017896ea61Andy McFadden        meth = dvmGetVirtualizedMethod(clazz, (Method*)methodID);           \
2017f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (meth == NULL) {                                                 \
2018f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return _retfail;                                                \
2019f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }                                                                   \
2020f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        va_start(args, methodID);                                           \
20210647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes        dvmCallMethodV(ts.self(), meth, obj, true, &result, args);          \
20220647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes        if (_isref && !dvmCheckException(ts.self()))                        \
2023de68817bdae0ca038d824ba79a70ac17cae405e6Elliott Hughes            result.l = (Object*)addLocalReference(ts.self(), result.l);           \
2024f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        va_end(args);                                                       \
2025f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return _retok;                                                      \
2026f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }                                                                       \
2027ab00d455ea67fbf4090567bb09ead8017896ea61Andy McFadden    static _ctype CallNonvirtual##_jname##MethodV(JNIEnv* env, jobject jobj,\
2028ab00d455ea67fbf4090567bb09ead8017896ea61Andy McFadden        jclass jclazz, jmethodID methodID, va_list args)                    \
2029f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    {                                                                       \
20300647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes        ScopedJniThreadState ts(env);                                       \
2031de68817bdae0ca038d824ba79a70ac17cae405e6Elliott Hughes        Object* obj = dvmDecodeIndirectRef(ts.self(), jobj);                      \
2032de68817bdae0ca038d824ba79a70ac17cae405e6Elliott Hughes        ClassObject* clazz = (ClassObject*) dvmDecodeIndirectRef(ts.self(), jclazz); \
2033f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        const Method* meth;                                                 \
2034f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        JValue result;                                                      \
2035ab00d455ea67fbf4090567bb09ead8017896ea61Andy McFadden        meth = dvmGetVirtualizedMethod(clazz, (Method*)methodID);           \
2036f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (meth == NULL) {                                                 \
2037f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return _retfail;                                                \
2038f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }                                                                   \
20390647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes        dvmCallMethodV(ts.self(), meth, obj, true, &result, args);          \
20400647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes        if (_isref && !dvmCheckException(ts.self()))                        \
2041de68817bdae0ca038d824ba79a70ac17cae405e6Elliott Hughes            result.l = (Object*)addLocalReference(ts.self(), result.l);           \
2042f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return _retok;                                                      \
2043f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }                                                                       \
2044ab00d455ea67fbf4090567bb09ead8017896ea61Andy McFadden    static _ctype CallNonvirtual##_jname##MethodA(JNIEnv* env, jobject jobj,\
2045ab00d455ea67fbf4090567bb09ead8017896ea61Andy McFadden        jclass jclazz, jmethodID methodID, jvalue* args)                    \
2046f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    {                                                                       \
20470647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes        ScopedJniThreadState ts(env);                                       \
2048de68817bdae0ca038d824ba79a70ac17cae405e6Elliott Hughes        Object* obj = dvmDecodeIndirectRef(ts.self(), jobj); \
2049de68817bdae0ca038d824ba79a70ac17cae405e6Elliott Hughes        ClassObject* clazz = (ClassObject*) dvmDecodeIndirectRef(ts.self(), jclazz); \
2050f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        const Method* meth;                                                 \
2051f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        JValue result;                                                      \
2052ab00d455ea67fbf4090567bb09ead8017896ea61Andy McFadden        meth = dvmGetVirtualizedMethod(clazz, (Method*)methodID);           \
2053f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (meth == NULL) {                                                 \
2054f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return _retfail;                                                \
2055f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }                                                                   \
20560647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes        dvmCallMethodA(ts.self(), meth, obj, true, &result, args);          \
20570647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes        if (_isref && !dvmCheckException(ts.self()))                        \
2058de68817bdae0ca038d824ba79a70ac17cae405e6Elliott Hughes            result.l = (Object*)addLocalReference(ts.self(), result.l);           \
2059f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return _retok;                                                      \
2060f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
20610647d294bab9312be67a9032adfa4f0b9ba0984aElliott HughesCALL_NONVIRTUAL(jobject, Object, NULL, (jobject) result.l, true);
2062f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectCALL_NONVIRTUAL(jboolean, Boolean, 0, result.z, false);
2063f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectCALL_NONVIRTUAL(jbyte, Byte, 0, result.b, false);
2064f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectCALL_NONVIRTUAL(jchar, Char, 0, result.c, false);
2065f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectCALL_NONVIRTUAL(jshort, Short, 0, result.s, false);
2066f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectCALL_NONVIRTUAL(jint, Int, 0, result.i, false);
2067f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectCALL_NONVIRTUAL(jlong, Long, 0, result.j, false);
2068f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectCALL_NONVIRTUAL(jfloat, Float, 0.0f, result.f, false);
2069f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectCALL_NONVIRTUAL(jdouble, Double, 0.0, result.d, false);
2070f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectCALL_NONVIRTUAL(void, Void, , , false);
2071f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2072f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2073f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
2074f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Call a static method.
2075f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
2076f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#define CALL_STATIC(_ctype, _jname, _retfail, _retok, _isref)               \
2077ab00d455ea67fbf4090567bb09ead8017896ea61Andy McFadden    static _ctype CallStatic##_jname##Method(JNIEnv* env, jclass jclazz,    \
2078f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        jmethodID methodID, ...)                                            \
2079f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    {                                                                       \
2080ab00d455ea67fbf4090567bb09ead8017896ea61Andy McFadden        UNUSED_PARAMETER(jclazz);                                           \
20810647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes        ScopedJniThreadState ts(env);                                       \
2082f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        JValue result;                                                      \
2083f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        va_list args;                                                       \
2084f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        va_start(args, methodID);                                           \
20850647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes        dvmCallMethodV(ts.self(), (Method*)methodID, NULL, true, &result, args);\
2086f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        va_end(args);                                                       \
20870647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes        if (_isref && !dvmCheckException(ts.self()))                        \
2088de68817bdae0ca038d824ba79a70ac17cae405e6Elliott Hughes            result.l = (Object*)addLocalReference(ts.self(), result.l);           \
2089f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return _retok;                                                      \
2090f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }                                                                       \
2091ab00d455ea67fbf4090567bb09ead8017896ea61Andy McFadden    static _ctype CallStatic##_jname##MethodV(JNIEnv* env, jclass jclazz,   \
2092f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        jmethodID methodID, va_list args)                                   \
2093f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    {                                                                       \
2094ab00d455ea67fbf4090567bb09ead8017896ea61Andy McFadden        UNUSED_PARAMETER(jclazz);                                           \
20950647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes        ScopedJniThreadState ts(env);                                       \
2096f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        JValue result;                                                      \
20970647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes        dvmCallMethodV(ts.self(), (Method*)methodID, NULL, true, &result, args);\
20980647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes        if (_isref && !dvmCheckException(ts.self()))                        \
2099de68817bdae0ca038d824ba79a70ac17cae405e6Elliott Hughes            result.l = (Object*)addLocalReference(ts.self(), result.l);           \
2100f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return _retok;                                                      \
2101f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }                                                                       \
2102ab00d455ea67fbf4090567bb09ead8017896ea61Andy McFadden    static _ctype CallStatic##_jname##MethodA(JNIEnv* env, jclass jclazz,   \
2103f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        jmethodID methodID, jvalue* args)                                   \
2104f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    {                                                                       \
2105ab00d455ea67fbf4090567bb09ead8017896ea61Andy McFadden        UNUSED_PARAMETER(jclazz);                                           \
21060647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes        ScopedJniThreadState ts(env);                                       \
2107f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        JValue result;                                                      \
21080647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes        dvmCallMethodA(ts.self(), (Method*)methodID, NULL, true, &result, args);\
21090647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes        if (_isref && !dvmCheckException(ts.self()))                        \
2110de68817bdae0ca038d824ba79a70ac17cae405e6Elliott Hughes            result.l = (Object*)addLocalReference(ts.self(), result.l);           \
2111f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return _retok;                                                      \
2112f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
21130647d294bab9312be67a9032adfa4f0b9ba0984aElliott HughesCALL_STATIC(jobject, Object, NULL, (jobject) result.l, true);
2114f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectCALL_STATIC(jboolean, Boolean, 0, result.z, false);
2115f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectCALL_STATIC(jbyte, Byte, 0, result.b, false);
2116f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectCALL_STATIC(jchar, Char, 0, result.c, false);
2117f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectCALL_STATIC(jshort, Short, 0, result.s, false);
2118f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectCALL_STATIC(jint, Int, 0, result.i, false);
2119f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectCALL_STATIC(jlong, Long, 0, result.j, false);
2120f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectCALL_STATIC(jfloat, Float, 0.0f, result.f, false);
2121f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectCALL_STATIC(jdouble, Double, 0.0, result.d, false);
2122f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectCALL_STATIC(void, Void, , , false);
2123f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2124f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
2125f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Create a new String from Unicode data.
2126f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
2127f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * If "len" is zero, we will return an empty string even if "unicodeChars"
2128f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * is NULL.  (The JNI spec is vague here.)
2129f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
213023ba9600c0207ef406513fce4c0278796e0b9415Elliott Hughesstatic jstring NewString(JNIEnv* env, const jchar* unicodeChars, jsize len) {
21310647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    ScopedJniThreadState ts(env);
2132ab00d455ea67fbf4090567bb09ead8017896ea61Andy McFadden    StringObject* jstr = dvmCreateStringFromUnicode(unicodeChars, len);
2133ab00d455ea67fbf4090567bb09ead8017896ea61Andy McFadden    if (jstr == NULL) {
21340647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes        return NULL;
2135f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
21360647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    dvmReleaseTrackedAlloc((Object*) jstr, NULL);
2137de68817bdae0ca038d824ba79a70ac17cae405e6Elliott Hughes    return (jstring) addLocalReference(ts.self(), (Object*) jstr);
2138f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
2139f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2140f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
2141f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Return the length of a String in Unicode character units.
2142f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
214323ba9600c0207ef406513fce4c0278796e0b9415Elliott Hughesstatic jsize GetStringLength(JNIEnv* env, jstring jstr) {
21440647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    ScopedJniThreadState ts(env);
2145de68817bdae0ca038d824ba79a70ac17cae405e6Elliott Hughes    StringObject* strObj = (StringObject*) dvmDecodeIndirectRef(ts.self(), jstr);
2146d8a3f9fa1951e552f5f65c2914689083cc0c46c2Elliott Hughes    return strObj->length();
2147f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
2148f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2149ab00d455ea67fbf4090567bb09ead8017896ea61Andy McFadden
2150f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
2151ab00d455ea67fbf4090567bb09ead8017896ea61Andy McFadden * Get a string's character data.
2152f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
2153f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The result is guaranteed to be valid until ReleaseStringChars is
2154ab00d455ea67fbf4090567bb09ead8017896ea61Andy McFadden * called, which means we have to pin it or return a copy.
2155f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
215623ba9600c0207ef406513fce4c0278796e0b9415Elliott Hughesstatic const jchar* GetStringChars(JNIEnv* env, jstring jstr, jboolean* isCopy) {
21570647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    ScopedJniThreadState ts(env);
2158f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2159de68817bdae0ca038d824ba79a70ac17cae405e6Elliott Hughes    StringObject* strObj = (StringObject*) dvmDecodeIndirectRef(ts.self(), jstr);
2160d8a3f9fa1951e552f5f65c2914689083cc0c46c2Elliott Hughes    ArrayObject* strChars = strObj->array();
2161ab00d455ea67fbf4090567bb09ead8017896ea61Andy McFadden
2162ab00d455ea67fbf4090567bb09ead8017896ea61Andy McFadden    pinPrimitiveArray(strChars);
2163f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2164d8a3f9fa1951e552f5f65c2914689083cc0c46c2Elliott Hughes    const u2* data = strObj->chars();
21650647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    if (isCopy != NULL) {
2166f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        *isCopy = JNI_FALSE;
21670647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    }
21680647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    return (jchar*) data;
2169f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
2170f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2171f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
2172f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Release our grip on some characters from a string.
2173f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
217423ba9600c0207ef406513fce4c0278796e0b9415Elliott Hughesstatic void ReleaseStringChars(JNIEnv* env, jstring jstr, const jchar* chars) {
21750647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    ScopedJniThreadState ts(env);
2176de68817bdae0ca038d824ba79a70ac17cae405e6Elliott Hughes    StringObject* strObj = (StringObject*) dvmDecodeIndirectRef(ts.self(), jstr);
2177d8a3f9fa1951e552f5f65c2914689083cc0c46c2Elliott Hughes    ArrayObject* strChars = strObj->array();
2178ab00d455ea67fbf4090567bb09ead8017896ea61Andy McFadden    unpinPrimitiveArray(strChars);
2179f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
2180f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2181f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
2182f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Create a new java.lang.String object from chars in modified UTF-8 form.
2183f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
2184f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The spec doesn't say how to handle a NULL string.  Popular desktop VMs
2185f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * accept it and return a NULL pointer in response.
2186f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
218723ba9600c0207ef406513fce4c0278796e0b9415Elliott Hughesstatic jstring NewStringUTF(JNIEnv* env, const char* bytes) {
21880647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    ScopedJniThreadState ts(env);
2189f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (bytes == NULL) {
21900647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes        return NULL;
2191f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
21920647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    /* note newStr could come back NULL on OOM */
21930647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    StringObject* newStr = dvmCreateStringFromCstr(bytes);
2194de68817bdae0ca038d824ba79a70ac17cae405e6Elliott Hughes    jstring result = (jstring) addLocalReference(ts.self(), (Object*) newStr);
21950647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    dvmReleaseTrackedAlloc((Object*)newStr, NULL);
2196ab00d455ea67fbf4090567bb09ead8017896ea61Andy McFadden    return result;
2197f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
2198f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2199f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
2200f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Return the length in bytes of the modified UTF-8 form of the string.
2201f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
220223ba9600c0207ef406513fce4c0278796e0b9415Elliott Hughesstatic jsize GetStringUTFLength(JNIEnv* env, jstring jstr) {
22030647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    ScopedJniThreadState ts(env);
2204de68817bdae0ca038d824ba79a70ac17cae405e6Elliott Hughes    StringObject* strObj = (StringObject*) dvmDecodeIndirectRef(ts.self(), jstr);
2205d8a3f9fa1951e552f5f65c2914689083cc0c46c2Elliott Hughes    if (strObj == NULL) {
2206d8a3f9fa1951e552f5f65c2914689083cc0c46c2Elliott Hughes        return 0; // Should we throw something or assert?
2207d8a3f9fa1951e552f5f65c2914689083cc0c46c2Elliott Hughes    }
2208d8a3f9fa1951e552f5f65c2914689083cc0c46c2Elliott Hughes    return strObj->utfLength();
2209f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
2210f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2211f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
2212f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Convert "string" to modified UTF-8 and return a pointer.  The returned
2213f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * value must be released with ReleaseStringUTFChars.
2214f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
2215f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * According to the JNI reference, "Returns a pointer to a UTF-8 string,
2216f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * or NULL if the operation fails. Returns NULL if and only if an invocation
2217f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * of this function has thrown an exception."
2218f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
2219f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The behavior here currently follows that of other open-source VMs, which
2220f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * quietly return NULL if "string" is NULL.  We should consider throwing an
2221f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * NPE.  (The CheckJNI code blows up if you try to pass in a NULL string,
2222f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * which should catch this sort of thing during development.)  Certain other
2223f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * VMs will crash with a segmentation fault.
2224f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
222523ba9600c0207ef406513fce4c0278796e0b9415Elliott Hughesstatic const char* GetStringUTFChars(JNIEnv* env, jstring jstr, jboolean* isCopy) {
22260647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    ScopedJniThreadState ts(env);
2227ab00d455ea67fbf4090567bb09ead8017896ea61Andy McFadden    if (jstr == NULL) {
2228f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* this shouldn't happen; throw NPE? */
22290647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes        return NULL;
22300647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    }
22310647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    if (isCopy != NULL) {
22320647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes        *isCopy = JNI_TRUE;
22330647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    }
2234de68817bdae0ca038d824ba79a70ac17cae405e6Elliott Hughes    StringObject* strObj = (StringObject*) dvmDecodeIndirectRef(ts.self(), jstr);
22350647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    char* newStr = dvmCreateCstrFromString(strObj);
22360647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    if (newStr == NULL) {
22370647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes        /* assume memory failure */
22380647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes        dvmThrowOutOfMemoryError("native heap string alloc failed");
2239f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2240f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return newStr;
2241f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
2242f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2243f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
2244f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Release a string created by GetStringUTFChars().
2245f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
224623ba9600c0207ef406513fce4c0278796e0b9415Elliott Hughesstatic void ReleaseStringUTFChars(JNIEnv* env, jstring jstr, const char* utf) {
22470647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    ScopedJniThreadState ts(env);
22480647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    free((char*) utf);
2249f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
2250f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2251f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
2252f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Return the capacity of the array.
2253f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
225423ba9600c0207ef406513fce4c0278796e0b9415Elliott Hughesstatic jsize GetArrayLength(JNIEnv* env, jarray jarr) {
22550647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    ScopedJniThreadState ts(env);
2256de68817bdae0ca038d824ba79a70ac17cae405e6Elliott Hughes    ArrayObject* arrObj = (ArrayObject*) dvmDecodeIndirectRef(ts.self(), jarr);
22570647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    return arrObj->length;
2258f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
2259f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2260f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
2261f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Construct a new array that holds objects from class "elementClass".
2262f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
2263f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic jobjectArray NewObjectArray(JNIEnv* env, jsize length,
2264ab00d455ea67fbf4090567bb09ead8017896ea61Andy McFadden    jclass jelementClass, jobject jinitialElement)
2265f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
22660647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    ScopedJniThreadState ts(env);
2267f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2268c759b9f089e8e09df335a030d0555366d9395aebAndy McFadden    if (jelementClass == NULL) {
2269a8b4a0eec5e3ab181b3d26223c84c556bead06c8Elliott Hughes        dvmThrowNullPointerException("JNI NewObjectArray elementClass == NULL");
22700647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes        return NULL;
2271f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2272f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2273de68817bdae0ca038d824ba79a70ac17cae405e6Elliott Hughes    ClassObject* elemClassObj = (ClassObject*) dvmDecodeIndirectRef(ts.self(), jelementClass);
2274a4f4a73edf03cd08b5b2d775913bcac674a117bbCarl Shapiro    ClassObject* arrayClass = dvmFindArrayClassForElement(elemClassObj);
2275a4f4a73edf03cd08b5b2d775913bcac674a117bbCarl Shapiro    ArrayObject* newObj = dvmAllocArrayByClass(arrayClass, length, ALLOC_DEFAULT);
2276f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (newObj == NULL) {
22770647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes        assert(dvmCheckException(ts.self()));
22780647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes        return NULL;
2279f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2280de68817bdae0ca038d824ba79a70ac17cae405e6Elliott Hughes    jobjectArray newArray = (jobjectArray) addLocalReference(ts.self(), (Object*) newObj);
2281f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmReleaseTrackedAlloc((Object*) newObj, NULL);
2282f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2283f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
2284a4f4a73edf03cd08b5b2d775913bcac674a117bbCarl Shapiro     * Initialize the array.
2285f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
2286ab00d455ea67fbf4090567bb09ead8017896ea61Andy McFadden    if (jinitialElement != NULL) {
2287de68817bdae0ca038d824ba79a70ac17cae405e6Elliott Hughes        Object* initialElement = dvmDecodeIndirectRef(ts.self(), jinitialElement);
22880647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes        Object** arrayData = (Object**) (void*) newObj->contents;
2289a4f4a73edf03cd08b5b2d775913bcac674a117bbCarl Shapiro        for (jsize i = 0; i < length; ++i) {
2290a4f4a73edf03cd08b5b2d775913bcac674a117bbCarl Shapiro            arrayData[i] = initialElement;
22910647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes        }
2292f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2293f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2294ab00d455ea67fbf4090567bb09ead8017896ea61Andy McFadden    return newArray;
2295f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
2296f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
22970016024cdd2bdeef3b98c92f7a8f40a2bc1ff42dElliott Hughesstatic bool checkArrayElementBounds(ArrayObject* arrayObj, jsize index) {
22980016024cdd2bdeef3b98c92f7a8f40a2bc1ff42dElliott Hughes    assert(arrayObj != NULL);
22990016024cdd2bdeef3b98c92f7a8f40a2bc1ff42dElliott Hughes    if (index < 0 || index >= (int) arrayObj->length) {
230047f58250c5177adba475b0b11a36151ac0ce9ab9Dan Bornstein        dvmThrowArrayIndexOutOfBoundsException(arrayObj->length, index);
23010016024cdd2bdeef3b98c92f7a8f40a2bc1ff42dElliott Hughes        return false;
23020016024cdd2bdeef3b98c92f7a8f40a2bc1ff42dElliott Hughes    }
23030016024cdd2bdeef3b98c92f7a8f40a2bc1ff42dElliott Hughes    return true;
23040016024cdd2bdeef3b98c92f7a8f40a2bc1ff42dElliott Hughes}
23050016024cdd2bdeef3b98c92f7a8f40a2bc1ff42dElliott Hughes
2306f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
2307f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Get one element of an Object array.
2308f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
2309f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Add the object to the local references table in case the array goes away.
2310f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
231123ba9600c0207ef406513fce4c0278796e0b9415Elliott Hughesstatic jobject GetObjectArrayElement(JNIEnv* env, jobjectArray jarr, jsize index) {
23120647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    ScopedJniThreadState ts(env);
2313f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2314de68817bdae0ca038d824ba79a70ac17cae405e6Elliott Hughes    ArrayObject* arrayObj = (ArrayObject*) dvmDecodeIndirectRef(ts.self(), jarr);
23150016024cdd2bdeef3b98c92f7a8f40a2bc1ff42dElliott Hughes    if (!checkArrayElementBounds(arrayObj, index)) {
23160647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes        return NULL;
2317f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2318f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
23190647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    Object* value = ((Object**) (void*) arrayObj->contents)[index];
2320de68817bdae0ca038d824ba79a70ac17cae405e6Elliott Hughes    return addLocalReference(ts.self(), value);
2321f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
2322f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2323f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
2324f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Set one element of an Object array.
2325f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
232623ba9600c0207ef406513fce4c0278796e0b9415Elliott Hughesstatic void SetObjectArrayElement(JNIEnv* env, jobjectArray jarr, jsize index, jobject jobj) {
23270647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    ScopedJniThreadState ts(env);
2328f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2329de68817bdae0ca038d824ba79a70ac17cae405e6Elliott Hughes    ArrayObject* arrayObj = (ArrayObject*) dvmDecodeIndirectRef(ts.self(), jarr);
23300016024cdd2bdeef3b98c92f7a8f40a2bc1ff42dElliott Hughes    if (!checkArrayElementBounds(arrayObj, index)) {
23310647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes        return;
2332f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2333f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
233466a6e44bafabc957eb4eaaddbbb21e5f130c8aadElliott Hughes    Object* obj = dvmDecodeIndirectRef(ts.self(), jobj);
233566a6e44bafabc957eb4eaaddbbb21e5f130c8aadElliott Hughes
233666a6e44bafabc957eb4eaaddbbb21e5f130c8aadElliott Hughes    if (obj != NULL && !dvmCanPutArrayElement(obj->clazz, arrayObj->clazz)) {
233766a6e44bafabc957eb4eaaddbbb21e5f130c8aadElliott Hughes      ALOGV("Can't put a '%s'(%p) into array type='%s'(%p)",
233866a6e44bafabc957eb4eaaddbbb21e5f130c8aadElliott Hughes            obj->clazz->descriptor, obj,
2339bb046193c2da5d43a57b2fa8a17a0f634bf003baElliott Hughes            arrayObj->clazz->descriptor, arrayObj);
234066a6e44bafabc957eb4eaaddbbb21e5f130c8aadElliott Hughes      dvmThrowArrayStoreExceptionIncompatibleElement(obj->clazz, arrayObj->clazz);
234166a6e44bafabc957eb4eaaddbbb21e5f130c8aadElliott Hughes      return;
234266a6e44bafabc957eb4eaaddbbb21e5f130c8aadElliott Hughes    }
234366a6e44bafabc957eb4eaaddbbb21e5f130c8aadElliott Hughes
234492c1f6f1b4249e4e379452ee7b49f027052bf4ceSteve Block    //ALOGV("JNI: set element %d in array %p to %p", index, array, value);
2345f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2346364f9d924cbd9d392744a66f80cc084c3d80caf0Barry Hayes    dvmSetObjectArrayElement(arrayObj, index, obj);
2347f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
2348f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2349f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
2350f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Create a new array of primitive elements.
2351f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
23520647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes#define NEW_PRIMITIVE_ARRAY(_artype, _jname, _typechar) \
23530647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    static _artype New##_jname##Array(JNIEnv* env, jsize length) { \
23540647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes        ScopedJniThreadState ts(env); \
23550647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes        ArrayObject* arrayObj = dvmAllocPrimitiveArray(_typechar, length, ALLOC_DEFAULT); \
23560647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes        if (arrayObj == NULL) { \
23570647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes            return NULL; \
23580647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes        } \
2359de68817bdae0ca038d824ba79a70ac17cae405e6Elliott Hughes        _artype result = (_artype) addLocalReference(ts.self(), (Object*) arrayObj); \
23600647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes        dvmReleaseTrackedAlloc((Object*) arrayObj, NULL); \
23610647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes        return result; \
2362f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2363f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectNEW_PRIMITIVE_ARRAY(jbooleanArray, Boolean, 'Z');
2364f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectNEW_PRIMITIVE_ARRAY(jbyteArray, Byte, 'B');
2365f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectNEW_PRIMITIVE_ARRAY(jcharArray, Char, 'C');
2366f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectNEW_PRIMITIVE_ARRAY(jshortArray, Short, 'S');
2367f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectNEW_PRIMITIVE_ARRAY(jintArray, Int, 'I');
2368f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectNEW_PRIMITIVE_ARRAY(jlongArray, Long, 'J');
2369f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectNEW_PRIMITIVE_ARRAY(jfloatArray, Float, 'F');
2370f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectNEW_PRIMITIVE_ARRAY(jdoubleArray, Double, 'D');
2371f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2372f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
2373f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Get a pointer to a C array of primitive elements from an array object
2374f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * of the matching type.
2375f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
2376ab00d455ea67fbf4090567bb09ead8017896ea61Andy McFadden * In a compacting GC, we either need to return a copy of the elements or
2377ab00d455ea67fbf4090567bb09ead8017896ea61Andy McFadden * "pin" the memory.  Otherwise we run the risk of native code using the
2378ab00d455ea67fbf4090567bb09ead8017896ea61Andy McFadden * buffer as the destination of e.g. a blocking read() call that wakes up
2379f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * during a GC.
2380f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
23810647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes#define GET_PRIMITIVE_ARRAY_ELEMENTS(_ctype, _jname) \
23820647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    static _ctype* Get##_jname##ArrayElements(JNIEnv* env, \
23830647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes        _ctype##Array jarr, jboolean* isCopy) \
23840647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    { \
23850647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes        ScopedJniThreadState ts(env); \
2386de68817bdae0ca038d824ba79a70ac17cae405e6Elliott Hughes        ArrayObject* arrayObj = (ArrayObject*) dvmDecodeIndirectRef(ts.self(), jarr); \
23870647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes        pinPrimitiveArray(arrayObj); \
23880647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes        _ctype* data = (_ctype*) (void*) arrayObj->contents; \
23890647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes        if (isCopy != NULL) { \
23900647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes            *isCopy = JNI_FALSE; \
23910647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes        } \
23920647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes        return data; \
2393f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2394f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2395f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
2396f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Release the storage locked down by the "get" function.
2397f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
2398ab00d455ea67fbf4090567bb09ead8017896ea61Andy McFadden * The spec says, "'mode' has no effect if 'elems' is not a copy of the
2399f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * elements in 'array'."  They apparently did not anticipate the need to
2400ab00d455ea67fbf4090567bb09ead8017896ea61Andy McFadden * un-pin memory.
2401f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
2402f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#define RELEASE_PRIMITIVE_ARRAY_ELEMENTS(_ctype, _jname)                    \
2403f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    static void Release##_jname##ArrayElements(JNIEnv* env,                 \
2404ab00d455ea67fbf4090567bb09ead8017896ea61Andy McFadden        _ctype##Array jarr, _ctype* elems, jint mode)                       \
2405f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    {                                                                       \
2406f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        UNUSED_PARAMETER(elems);                                            \
2407ab00d455ea67fbf4090567bb09ead8017896ea61Andy McFadden        if (mode != JNI_COMMIT) {                                           \
24080647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes            ScopedJniThreadState ts(env);                                   \
2409de68817bdae0ca038d824ba79a70ac17cae405e6Elliott Hughes            ArrayObject* arrayObj = (ArrayObject*) dvmDecodeIndirectRef(ts.self(), jarr); \
2410ab00d455ea67fbf4090567bb09ead8017896ea61Andy McFadden            unpinPrimitiveArray(arrayObj);                                  \
2411ab00d455ea67fbf4090567bb09ead8017896ea61Andy McFadden        }                                                                   \
2412f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2413f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
24140016024cdd2bdeef3b98c92f7a8f40a2bc1ff42dElliott Hughesstatic void throwArrayRegionOutOfBounds(ArrayObject* arrayObj, jsize start,
24150016024cdd2bdeef3b98c92f7a8f40a2bc1ff42dElliott Hughes    jsize len, const char* arrayIdentifier)
24160016024cdd2bdeef3b98c92f7a8f40a2bc1ff42dElliott Hughes{
24170b8b293f228b3d341054bc1fad8a92d6e533b4ddDan Bornstein    dvmThrowExceptionFmt(gDvm.exArrayIndexOutOfBoundsException,
24180016024cdd2bdeef3b98c92f7a8f40a2bc1ff42dElliott Hughes        "%s offset=%d length=%d %s.length=%d",
2419a62c3a0ab3fcdde37f47d16e9699a935ae7a8e88Carl Shapiro        arrayObj->clazz->descriptor, start, len, arrayIdentifier,
24200016024cdd2bdeef3b98c92f7a8f40a2bc1ff42dElliott Hughes        arrayObj->length);
24210016024cdd2bdeef3b98c92f7a8f40a2bc1ff42dElliott Hughes}
24220016024cdd2bdeef3b98c92f7a8f40a2bc1ff42dElliott Hughes
2423f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
2424f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Copy a section of a primitive array to a buffer.
2425f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
24260647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes#define GET_PRIMITIVE_ARRAY_REGION(_ctype, _jname) \
24270647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    static void Get##_jname##ArrayRegion(JNIEnv* env, \
24280647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes        _ctype##Array jarr, jsize start, jsize len, _ctype* buf) \
24290647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    { \
24300647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes        ScopedJniThreadState ts(env); \
2431de68817bdae0ca038d824ba79a70ac17cae405e6Elliott Hughes        ArrayObject* arrayObj = (ArrayObject*) dvmDecodeIndirectRef(ts.self(), jarr); \
24320647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes        _ctype* data = (_ctype*) (void*) arrayObj->contents; \
2433f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (start < 0 || len < 0 || start + len > (int) arrayObj->length) { \
24340647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes            throwArrayRegionOutOfBounds(arrayObj, start, len, "src"); \
24350647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes        } else { \
24360647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes            memcpy(buf, data + start, len * sizeof(_ctype)); \
24370647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes        } \
2438f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2439f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2440f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
24410d615c3ce5bf97ae65b9347ee77968f38620d5e8Andy McFadden * Copy a section of a primitive array from a buffer.
2442f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
24430647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes#define SET_PRIMITIVE_ARRAY_REGION(_ctype, _jname) \
24440647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    static void Set##_jname##ArrayRegion(JNIEnv* env, \
24450647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes        _ctype##Array jarr, jsize start, jsize len, const _ctype* buf) \
24460647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    { \
24470647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes        ScopedJniThreadState ts(env); \
2448de68817bdae0ca038d824ba79a70ac17cae405e6Elliott Hughes        ArrayObject* arrayObj = (ArrayObject*) dvmDecodeIndirectRef(ts.self(), jarr); \
24490647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes        _ctype* data = (_ctype*) (void*) arrayObj->contents; \
2450f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (start < 0 || len < 0 || start + len > (int) arrayObj->length) { \
24510647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes            throwArrayRegionOutOfBounds(arrayObj, start, len, "dst"); \
24520647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes        } else { \
24530647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes            memcpy(data + start, buf, len * sizeof(_ctype)); \
24540647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes        } \
2455f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2456f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2457f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
2458f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 4-in-1:
2459f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *  Get<Type>ArrayElements
2460f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *  Release<Type>ArrayElements
2461f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *  Get<Type>ArrayRegion
2462f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *  Set<Type>ArrayRegion
2463f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
2464f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#define PRIMITIVE_ARRAY_FUNCTIONS(_ctype, _jname)                           \
2465f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    GET_PRIMITIVE_ARRAY_ELEMENTS(_ctype, _jname);                           \
2466f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    RELEASE_PRIMITIVE_ARRAY_ELEMENTS(_ctype, _jname);                       \
2467f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    GET_PRIMITIVE_ARRAY_REGION(_ctype, _jname);                             \
2468f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    SET_PRIMITIVE_ARRAY_REGION(_ctype, _jname);
2469f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2470f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectPRIMITIVE_ARRAY_FUNCTIONS(jboolean, Boolean);
2471f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectPRIMITIVE_ARRAY_FUNCTIONS(jbyte, Byte);
2472f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectPRIMITIVE_ARRAY_FUNCTIONS(jchar, Char);
2473f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectPRIMITIVE_ARRAY_FUNCTIONS(jshort, Short);
2474f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectPRIMITIVE_ARRAY_FUNCTIONS(jint, Int);
2475f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectPRIMITIVE_ARRAY_FUNCTIONS(jlong, Long);
2476f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectPRIMITIVE_ARRAY_FUNCTIONS(jfloat, Float);
2477f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectPRIMITIVE_ARRAY_FUNCTIONS(jdouble, Double);
2478f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2479f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
2480f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Register one or more native functions in one class.
24811e83b4d026199073c057edcb7836d06ae0716390Andy McFadden *
24821e83b4d026199073c057edcb7836d06ae0716390Andy McFadden * This can be called multiple times on the same method, allowing the
24831e83b4d026199073c057edcb7836d06ae0716390Andy McFadden * caller to redefine the method implementation at will.
2484f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
2485ab00d455ea67fbf4090567bb09ead8017896ea61Andy McFaddenstatic jint RegisterNatives(JNIEnv* env, jclass jclazz,
2486f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const JNINativeMethod* methods, jint nMethods)
2487f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
24880647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    ScopedJniThreadState ts(env);
2489f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2490de68817bdae0ca038d824ba79a70ac17cae405e6Elliott Hughes    ClassObject* clazz = (ClassObject*) dvmDecodeIndirectRef(ts.self(), jclazz);
2491f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2492f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (gDvm.verboseJni) {
24934308417beec548c2b2c06ecec4f7f4a965b09fb2Steve Block        ALOGI("[Registering JNI native methods for class %s]",
2494ab00d455ea67fbf4090567bb09ead8017896ea61Andy McFadden            clazz->descriptor);
2495f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2496f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
24970647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    for (int i = 0; i < nMethods; i++) {
2498ab00d455ea67fbf4090567bb09ead8017896ea61Andy McFadden        if (!dvmRegisterJNIMethod(clazz, methods[i].name,
2499ab00d455ea67fbf4090567bb09ead8017896ea61Andy McFadden                methods[i].signature, methods[i].fnPtr))
2500f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        {
25010647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes            return JNI_ERR;
2502f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2503f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
25040647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    return JNI_OK;
2505f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
2506f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2507f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
25081e83b4d026199073c057edcb7836d06ae0716390Andy McFadden * Un-register all native methods associated with the class.
25091e83b4d026199073c057edcb7836d06ae0716390Andy McFadden *
25101e83b4d026199073c057edcb7836d06ae0716390Andy McFadden * The JNI docs refer to this as a way to reload/relink native libraries,
25111e83b4d026199073c057edcb7836d06ae0716390Andy McFadden * and say it "should not be used in normal native code".  In particular,
25121e83b4d026199073c057edcb7836d06ae0716390Andy McFadden * there is no need to do this during shutdown, and you do not need to do
25131e83b4d026199073c057edcb7836d06ae0716390Andy McFadden * this before redefining a method implementation with RegisterNatives.
25141e83b4d026199073c057edcb7836d06ae0716390Andy McFadden *
25151e83b4d026199073c057edcb7836d06ae0716390Andy McFadden * It's chiefly useful for a native "plugin"-style library that wasn't
25161e83b4d026199073c057edcb7836d06ae0716390Andy McFadden * loaded with System.loadLibrary() (since there's no way to unload those).
25171e83b4d026199073c057edcb7836d06ae0716390Andy McFadden * For example, the library could upgrade itself by:
25181e83b4d026199073c057edcb7836d06ae0716390Andy McFadden *
25191e83b4d026199073c057edcb7836d06ae0716390Andy McFadden *  1. call UnregisterNatives to unbind the old methods
25201e83b4d026199073c057edcb7836d06ae0716390Andy McFadden *  2. ensure that no code is still executing inside it (somehow)
25211e83b4d026199073c057edcb7836d06ae0716390Andy McFadden *  3. dlclose() the library
25221e83b4d026199073c057edcb7836d06ae0716390Andy McFadden *  4. dlopen() the new library
25231e83b4d026199073c057edcb7836d06ae0716390Andy McFadden *  5. use RegisterNatives to bind the methods from the new library
25241e83b4d026199073c057edcb7836d06ae0716390Andy McFadden *
25251e83b4d026199073c057edcb7836d06ae0716390Andy McFadden * The above can work correctly without the UnregisterNatives call, but
25261e83b4d026199073c057edcb7836d06ae0716390Andy McFadden * creates a window of opportunity in which somebody might try to call a
25271e83b4d026199073c057edcb7836d06ae0716390Andy McFadden * method that is pointing at unmapped memory, crashing the VM.  In theory
25281e83b4d026199073c057edcb7836d06ae0716390Andy McFadden * the same guards that prevent dlclose() from unmapping executing code could
25291e83b4d026199073c057edcb7836d06ae0716390Andy McFadden * prevent that anyway, but with this we can be more thorough and also deal
25301e83b4d026199073c057edcb7836d06ae0716390Andy McFadden * with methods that only exist in the old or new form of the library (maybe
25311e83b4d026199073c057edcb7836d06ae0716390Andy McFadden * the lib wants to try the call and catch the UnsatisfiedLinkError).
2532f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
253323ba9600c0207ef406513fce4c0278796e0b9415Elliott Hughesstatic jint UnregisterNatives(JNIEnv* env, jclass jclazz) {
25340647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    ScopedJniThreadState ts(env);
25351e83b4d026199073c057edcb7836d06ae0716390Andy McFadden
2536de68817bdae0ca038d824ba79a70ac17cae405e6Elliott Hughes    ClassObject* clazz = (ClassObject*) dvmDecodeIndirectRef(ts.self(), jclazz);
25371e83b4d026199073c057edcb7836d06ae0716390Andy McFadden    if (gDvm.verboseJni) {
25384308417beec548c2b2c06ecec4f7f4a965b09fb2Steve Block        ALOGI("[Unregistering JNI native methods for class %s]",
25391e83b4d026199073c057edcb7836d06ae0716390Andy McFadden            clazz->descriptor);
25401e83b4d026199073c057edcb7836d06ae0716390Andy McFadden    }
25411e83b4d026199073c057edcb7836d06ae0716390Andy McFadden    dvmUnregisterJNINativeMethods(clazz);
25421e83b4d026199073c057edcb7836d06ae0716390Andy McFadden    return JNI_OK;
2543f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
2544f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2545f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
2546f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Lock the monitor.
2547f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
2548f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We have to track all monitor enters and exits, so that we can undo any
2549f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * outstanding synchronization before the thread exits.
2550f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
255123ba9600c0207ef406513fce4c0278796e0b9415Elliott Hughesstatic jint MonitorEnter(JNIEnv* env, jobject jobj) {
25520647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    ScopedJniThreadState ts(env);
2553de68817bdae0ca038d824ba79a70ac17cae405e6Elliott Hughes    Object* obj = dvmDecodeIndirectRef(ts.self(), jobj);
25540647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    dvmLockObject(ts.self(), obj);
25550647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    trackMonitorEnter(ts.self(), obj);
2556f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return JNI_OK;
2557f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
2558f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2559f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
2560f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Unlock the monitor.
2561f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
2562f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Throws an IllegalMonitorStateException if the current thread
2563ab00d455ea67fbf4090567bb09ead8017896ea61Andy McFadden * doesn't own the monitor.  (dvmUnlockObject() takes care of the throw.)
2564f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
2565f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * According to the 1.6 spec, it's legal to call here with an exception
2566f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * pending.  If this fails, we'll stomp the original exception.
2567f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
256823ba9600c0207ef406513fce4c0278796e0b9415Elliott Hughesstatic jint MonitorExit(JNIEnv* env, jobject jobj) {
25690647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    ScopedJniThreadState ts(env);
2570de68817bdae0ca038d824ba79a70ac17cae405e6Elliott Hughes    Object* obj = dvmDecodeIndirectRef(ts.self(), jobj);
25710647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    bool success = dvmUnlockObject(ts.self(), obj);
25720647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    if (success) {
25730647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes        trackMonitorExit(ts.self(), obj);
25740647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    }
2575f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return success ? JNI_OK : JNI_ERR;
2576f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
2577f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2578f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
2579f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Return the JavaVM interface associated with the current thread.
2580f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
258123ba9600c0207ef406513fce4c0278796e0b9415Elliott Hughesstatic jint GetJavaVM(JNIEnv* env, JavaVM** vm) {
25820647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    ScopedJniThreadState ts(env);
2583d5c80e06a771bb34336c1ec5b0d9ce8a47ec4244Elliott Hughes    *vm = gDvmJni.jniVm;
25840647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    return (*vm == NULL) ? JNI_ERR : JNI_OK;
2585f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
2586f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2587f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
2588f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Copies "len" Unicode characters, from offset "start".
2589f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
259023ba9600c0207ef406513fce4c0278796e0b9415Elliott Hughesstatic void GetStringRegion(JNIEnv* env, jstring jstr, jsize start, jsize len, jchar* buf) {
25910647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    ScopedJniThreadState ts(env);
2592de68817bdae0ca038d824ba79a70ac17cae405e6Elliott Hughes    StringObject* strObj = (StringObject*) dvmDecodeIndirectRef(ts.self(), jstr);
2593d8a3f9fa1951e552f5f65c2914689083cc0c46c2Elliott Hughes    int strLen = strObj->length();
2594d8a3f9fa1951e552f5f65c2914689083cc0c46c2Elliott Hughes    if (((start|len) < 0) || (start + len > strLen)) {
25957a86c44bde10b37d8df17d0613072c4ef134189cDan Bornstein        dvmThrowStringIndexOutOfBoundsExceptionWithRegion(strLen, start, len);
25960647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes        return;
25970647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    }
2598d8a3f9fa1951e552f5f65c2914689083cc0c46c2Elliott Hughes    memcpy(buf, strObj->chars() + start, len * sizeof(u2));
2599f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
2600f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2601f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
2602f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Translates "len" Unicode characters, from offset "start", into
2603f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * modified UTF-8 encoding.
2604f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
260523ba9600c0207ef406513fce4c0278796e0b9415Elliott Hughesstatic void GetStringUTFRegion(JNIEnv* env, jstring jstr, jsize start, jsize len, char* buf) {
26060647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    ScopedJniThreadState ts(env);
2607de68817bdae0ca038d824ba79a70ac17cae405e6Elliott Hughes    StringObject* strObj = (StringObject*) dvmDecodeIndirectRef(ts.self(), jstr);
2608d8a3f9fa1951e552f5f65c2914689083cc0c46c2Elliott Hughes    int strLen = strObj->length();
2609d8a3f9fa1951e552f5f65c2914689083cc0c46c2Elliott Hughes    if (((start|len) < 0) || (start + len > strLen)) {
26107a86c44bde10b37d8df17d0613072c4ef134189cDan Bornstein        dvmThrowStringIndexOutOfBoundsExceptionWithRegion(strLen, start, len);
26110647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes        return;
26120647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    }
2613d8a3f9fa1951e552f5f65c2914689083cc0c46c2Elliott Hughes    dvmGetStringUtfRegion(strObj, start, len, buf);
2614f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
2615f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2616f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
2617f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Get a raw pointer to array data.
2618f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
2619f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The caller is expected to call "release" before doing any JNI calls
2620f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * or blocking I/O operations.
2621f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
2622ab00d455ea67fbf4090567bb09ead8017896ea61Andy McFadden * We need to pin the memory or block GC.
2623f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
262423ba9600c0207ef406513fce4c0278796e0b9415Elliott Hughesstatic void* GetPrimitiveArrayCritical(JNIEnv* env, jarray jarr, jboolean* isCopy) {
26250647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    ScopedJniThreadState ts(env);
2626de68817bdae0ca038d824ba79a70ac17cae405e6Elliott Hughes    ArrayObject* arrayObj = (ArrayObject*) dvmDecodeIndirectRef(ts.self(), jarr);
2627ab00d455ea67fbf4090567bb09ead8017896ea61Andy McFadden    pinPrimitiveArray(arrayObj);
26280647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    void* data = arrayObj->contents;
2629de68817bdae0ca038d824ba79a70ac17cae405e6Elliott Hughes    if (UNLIKELY(isCopy != NULL)) {
2630f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        *isCopy = JNI_FALSE;
26310647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    }
2632f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return data;
2633f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
2634f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2635f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
2636f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Release an array obtained with GetPrimitiveArrayCritical.
2637f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
263823ba9600c0207ef406513fce4c0278796e0b9415Elliott Hughesstatic void ReleasePrimitiveArrayCritical(JNIEnv* env, jarray jarr, void* carray, jint mode) {
2639ab00d455ea67fbf4090567bb09ead8017896ea61Andy McFadden    if (mode != JNI_COMMIT) {
26400647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes        ScopedJniThreadState ts(env);
2641de68817bdae0ca038d824ba79a70ac17cae405e6Elliott Hughes        ArrayObject* arrayObj = (ArrayObject*) dvmDecodeIndirectRef(ts.self(), jarr);
2642ab00d455ea67fbf4090567bb09ead8017896ea61Andy McFadden        unpinPrimitiveArray(arrayObj);
2643ab00d455ea67fbf4090567bb09ead8017896ea61Andy McFadden    }
2644f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
2645f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2646f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
2647f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Like GetStringChars, but with restricted use.
2648f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
264923ba9600c0207ef406513fce4c0278796e0b9415Elliott Hughesstatic const jchar* GetStringCritical(JNIEnv* env, jstring jstr, jboolean* isCopy) {
26500647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    ScopedJniThreadState ts(env);
26510647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes
2652de68817bdae0ca038d824ba79a70ac17cae405e6Elliott Hughes    StringObject* strObj = (StringObject*) dvmDecodeIndirectRef(ts.self(), jstr);
2653d8a3f9fa1951e552f5f65c2914689083cc0c46c2Elliott Hughes    ArrayObject* strChars = strObj->array();
2654ab00d455ea67fbf4090567bb09ead8017896ea61Andy McFadden
2655ab00d455ea67fbf4090567bb09ead8017896ea61Andy McFadden    pinPrimitiveArray(strChars);
2656f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2657d8a3f9fa1951e552f5f65c2914689083cc0c46c2Elliott Hughes    const u2* data = strObj->chars();
26580647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    if (isCopy != NULL) {
2659f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        *isCopy = JNI_FALSE;
26600647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    }
26610647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    return (jchar*) data;
2662f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
2663f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2664f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
2665f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Like ReleaseStringChars, but with restricted use.
2666f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
266723ba9600c0207ef406513fce4c0278796e0b9415Elliott Hughesstatic void ReleaseStringCritical(JNIEnv* env, jstring jstr, const jchar* carray) {
26680647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    ScopedJniThreadState ts(env);
2669de68817bdae0ca038d824ba79a70ac17cae405e6Elliott Hughes    StringObject* strObj = (StringObject*) dvmDecodeIndirectRef(ts.self(), jstr);
2670d8a3f9fa1951e552f5f65c2914689083cc0c46c2Elliott Hughes    ArrayObject* strChars = strObj->array();
2671ab00d455ea67fbf4090567bb09ead8017896ea61Andy McFadden    unpinPrimitiveArray(strChars);
2672f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
2673f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2674f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
2675f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Create a new weak global reference.
2676f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
267723ba9600c0207ef406513fce4c0278796e0b9415Elliott Hughesstatic jweak NewWeakGlobalRef(JNIEnv* env, jobject jobj) {
26780647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    ScopedJniThreadState ts(env);
2679de68817bdae0ca038d824ba79a70ac17cae405e6Elliott Hughes    Object *obj = dvmDecodeIndirectRef(ts.self(), jobj);
26800647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    return (jweak) addWeakGlobalReference(obj);
2681f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
2682f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2683f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
2684f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Delete the specified weak global reference.
2685f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
268623ba9600c0207ef406513fce4c0278796e0b9415Elliott Hughesstatic void DeleteWeakGlobalRef(JNIEnv* env, jweak wref) {
26870647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    ScopedJniThreadState ts(env);
2688e4c3b5ef3b418ea50f577a850bdbdfaf97718601Carl Shapiro    deleteWeakGlobalReference(wref);
2689f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
2690f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2691f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
2692f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Quick check for pending exceptions.
2693f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
2694f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * TODO: we should be able to skip the enter/exit macros here.
2695f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
269623ba9600c0207ef406513fce4c0278796e0b9415Elliott Hughesstatic jboolean ExceptionCheck(JNIEnv* env) {
26970647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    ScopedJniThreadState ts(env);
26980647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    return dvmCheckException(ts.self());
2699f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
2700f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2701f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
2702f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns the type of the object referred to by "obj".  It can be local,
2703f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * global, or weak global.
2704f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
2705f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * In the current implementation, references can be global and local at
2706f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the same time, so while the return value is accurate it may not tell
2707f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the whole story.
2708f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
270923ba9600c0207ef406513fce4c0278796e0b9415Elliott Hughesstatic jobjectRefType GetObjectRefType(JNIEnv* env, jobject jobj) {
27100647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    ScopedJniThreadState ts(env);
2711de68817bdae0ca038d824ba79a70ac17cae405e6Elliott Hughes    return dvmGetJNIRefType(ts.self(), jobj);
2712f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
2713f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2714f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
2715f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Allocate and return a new java.nio.ByteBuffer for this block of memory.
2716f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
271723ba9600c0207ef406513fce4c0278796e0b9415Elliott Hughesstatic jobject NewDirectByteBuffer(JNIEnv* env, void* address, jlong capacity) {
27180647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    ScopedJniThreadState ts(env);
2719f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
272085e8913705f23a5e799690134746219f64498f29Elliott Hughes    if (capacity < 0) {
272185e8913705f23a5e799690134746219f64498f29Elliott Hughes        ALOGE("JNI ERROR (app bug): negative buffer capacity: %lld", capacity);
272285e8913705f23a5e799690134746219f64498f29Elliott Hughes        ReportJniError();
272385e8913705f23a5e799690134746219f64498f29Elliott Hughes    }
272485e8913705f23a5e799690134746219f64498f29Elliott Hughes    if (address == NULL && capacity != 0) {
272585e8913705f23a5e799690134746219f64498f29Elliott Hughes        ALOGE("JNI ERROR (app bug): non-zero capacity for NULL pointer: %lld", capacity);
272685e8913705f23a5e799690134746219f64498f29Elliott Hughes        ReportJniError();
272785e8913705f23a5e799690134746219f64498f29Elliott Hughes    }
272885e8913705f23a5e799690134746219f64498f29Elliott Hughes
27299a58f1be9378c1de90ad3b5e34f1d842624d234dElliott Hughes    /* create an instance of java.nio.DirectByteBuffer */
27309a58f1be9378c1de90ad3b5e34f1d842624d234dElliott Hughes    ClassObject* bufferClazz = gDvm.classJavaNioDirectByteBuffer;
27310647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    if (!dvmIsClassInitialized(bufferClazz) && !dvmInitClass(bufferClazz)) {
27320647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes        return NULL;
27330647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    }
2734f30a7dc9a63e8bae2a738d343870a34c1a01460eElliott Hughes    Object* newObj = dvmAllocObject(bufferClazz, ALLOC_DONT_TRACK);
27350647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    if (newObj == NULL) {
27360647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes        return NULL;
27370647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    }
27380647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    /* call the constructor */
2739de68817bdae0ca038d824ba79a70ac17cae405e6Elliott Hughes    jobject result = addLocalReference(ts.self(), newObj);
27400647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    JValue unused;
27419a58f1be9378c1de90ad3b5e34f1d842624d234dElliott Hughes    dvmCallMethod(ts.self(), gDvm.methJavaNioDirectByteBuffer_init,
2742cbe8d43ea02e7885504a90461283d2bd8456aaa6Elliott Hughes            newObj, &unused, (jlong) address, (jint) capacity);
27430647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    if (dvmGetException(ts.self()) != NULL) {
2744de68817bdae0ca038d824ba79a70ac17cae405e6Elliott Hughes        deleteLocalReference(ts.self(), result);
27450647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes        return NULL;
2746f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
274799409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    return result;
2748f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
2749f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2750f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
2751f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Get the starting address of the buffer for the specified java.nio.Buffer.
2752f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
27538e5c78470229fd2f5474574081eaa4a2286aafeaAndy McFadden * If this is not a "direct" buffer, we return NULL.
2754f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
275523ba9600c0207ef406513fce4c0278796e0b9415Elliott Hughesstatic void* GetDirectBufferAddress(JNIEnv* env, jobject jbuf) {
27560647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    ScopedJniThreadState ts(env);
27578e5c78470229fd2f5474574081eaa4a2286aafeaAndy McFadden
27580647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    // All Buffer objects have an effectiveDirectAddress field.
2759de68817bdae0ca038d824ba79a70ac17cae405e6Elliott Hughes    Object* bufObj = dvmDecodeIndirectRef(ts.self(), jbuf);
2760bf3483153e2de90a8cf058fe5ba87cdb66a94e3cElliott Hughes    return (void*) dvmGetFieldLong(bufObj, gDvm.offJavaNioBuffer_effectiveDirectAddress);
2761f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
2762f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2763f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
2764f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Get the capacity of the buffer for the specified java.nio.Buffer.
2765f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
27668e5c78470229fd2f5474574081eaa4a2286aafeaAndy McFadden * Returns -1 if the object is not a direct buffer.  (We actually skip
27678e5c78470229fd2f5474574081eaa4a2286aafeaAndy McFadden * this check, since it's expensive to determine, and just return the
27688e5c78470229fd2f5474574081eaa4a2286aafeaAndy McFadden * capacity regardless.)
2769f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
277023ba9600c0207ef406513fce4c0278796e0b9415Elliott Hughesstatic jlong GetDirectBufferCapacity(JNIEnv* env, jobject jbuf) {
27710647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    ScopedJniThreadState ts(env);
2772f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
27738e5c78470229fd2f5474574081eaa4a2286aafeaAndy McFadden    /*
27748e5c78470229fd2f5474574081eaa4a2286aafeaAndy McFadden     * The capacity is always in the Buffer.capacity field.
27758e5c78470229fd2f5474574081eaa4a2286aafeaAndy McFadden     *
27768e5c78470229fd2f5474574081eaa4a2286aafeaAndy McFadden     * (The "check" version should verify that this is actually a Buffer,
27778e5c78470229fd2f5474574081eaa4a2286aafeaAndy McFadden     * but we're not required to do so here.)
27788e5c78470229fd2f5474574081eaa4a2286aafeaAndy McFadden     */
2779de68817bdae0ca038d824ba79a70ac17cae405e6Elliott Hughes    Object* buf = dvmDecodeIndirectRef(ts.self(), jbuf);
27800647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    return dvmGetFieldInt(buf, gDvm.offJavaNioBuffer_capacity);
2781f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
2782f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2783f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2784f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
2785f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * ===========================================================================
2786f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *      JNI invocation functions
2787f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * ===========================================================================
2788f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
2789f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2790f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
2791f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Handle AttachCurrentThread{AsDaemon}.
2792f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
2793f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We need to make sure the VM is actually running.  For example, if we start
2794f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * up, issue an Attach, and the VM exits almost immediately, by the time the
2795f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * attaching happens the VM could already be shutting down.
2796f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
2797f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * It's hard to avoid a race condition here because we don't want to hold
2798f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * a lock across the entire operation.  What we can do is temporarily
2799f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * increment the thread count to prevent a VM exit.
2800f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
2801f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This could potentially still have problems if a daemon thread calls here
2802f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * while the VM is shutting down.  dvmThreadSelf() will work, since it just
2803f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * uses pthread TLS, but dereferencing "vm" could fail.  Such is life when
2804f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * you shut down a VM while threads are still running inside it.
2805f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
2806f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Remember that some code may call this as a way to find the per-thread
2807f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * JNIEnv pointer.  Don't do excess work for that case.
2808f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
280923ba9600c0207ef406513fce4c0278796e0b9415Elliott Hughesstatic jint attachThread(JavaVM* vm, JNIEnv** p_env, void* thr_args, bool isDaemon) {
2810f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    JavaVMAttachArgs* args = (JavaVMAttachArgs*) thr_args;
2811f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2812f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
2813f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Return immediately if we're already one with the VM.
2814f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
281523ba9600c0207ef406513fce4c0278796e0b9415Elliott Hughes    Thread* self = dvmThreadSelf();
2816f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (self != NULL) {
2817f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        *p_env = self->jniEnv;
2818f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return JNI_OK;
2819f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2820f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2821f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
2822f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * No threads allowed in zygote mode.
2823f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
2824f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (gDvm.zygote) {
2825f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return JNI_ERR;
2826f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2827f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2828f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* increment the count to keep the VM from bailing while we run */
2829f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmLockThreadList(NULL);
2830f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (gDvm.nonDaemonThreadCount == 0) {
2831f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        // dead or dying
283292c1f6f1b4249e4e379452ee7b49f027052bf4ceSteve Block        ALOGV("Refusing to attach thread '%s' -- VM is shutting down",
2833f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            (thr_args == NULL) ? "(unknown)" : args->name);
2834f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmUnlockThreadList();
2835f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return JNI_ERR;
2836f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2837f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    gDvm.nonDaemonThreadCount++;
2838f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmUnlockThreadList();
2839f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2840f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* tweak the JavaVMAttachArgs as needed */
2841f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    JavaVMAttachArgs argsCopy;
2842f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (args == NULL) {
2843f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* allow the v1.1 calling convention */
2844f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        argsCopy.version = JNI_VERSION_1_2;
2845f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        argsCopy.name = NULL;
28460647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes        argsCopy.group = (jobject) dvmGetMainThreadGroup();
2847f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
2848f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        argsCopy.version = args->version;
2849f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        argsCopy.name = args->name;
28500647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes        if (args->group != NULL) {
285161e50bdecb9161ab87fbeb1d20da1a86ff7e8f59Elliott Hughes            argsCopy.group = (jobject) dvmDecodeIndirectRef(NULL, args->group);
28520647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes        } else {
28530647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes            argsCopy.group = (jobject) dvmGetMainThreadGroup();
28540647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes        }
2855f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2856f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
285723ba9600c0207ef406513fce4c0278796e0b9415Elliott Hughes    bool result = dvmAttachCurrentThread(&argsCopy, isDaemon);
2858f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2859f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* restore the count */
2860f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmLockThreadList(NULL);
2861f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    gDvm.nonDaemonThreadCount--;
2862f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmUnlockThreadList();
2863f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2864f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
2865f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Change the status to indicate that we're out in native code.  This
2866f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * call is not guarded with state-change macros, so we have to do it
2867f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * by hand.
2868f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
2869f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (result) {
2870f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        self = dvmThreadSelf();
2871f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(self != NULL);
2872f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmChangeStatus(self, THREAD_NATIVE);
2873f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        *p_env = self->jniEnv;
2874f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return JNI_OK;
2875f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
2876f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return JNI_ERR;
2877f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2878f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
2879f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2880f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
2881f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Attach the current thread to the VM.  If the thread is already attached,
2882f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * this is a no-op.
2883f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
288423ba9600c0207ef406513fce4c0278796e0b9415Elliott Hughesstatic jint AttachCurrentThread(JavaVM* vm, JNIEnv** p_env, void* thr_args) {
2885f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return attachThread(vm, p_env, thr_args, false);
2886f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
2887f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2888f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
2889f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Like AttachCurrentThread, but set the "daemon" flag.
2890f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
289123ba9600c0207ef406513fce4c0278796e0b9415Elliott Hughesstatic jint AttachCurrentThreadAsDaemon(JavaVM* vm, JNIEnv** p_env, void* thr_args)
2892f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
2893f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return attachThread(vm, p_env, thr_args, true);
2894f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
2895f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2896f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
2897f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Dissociate the current thread from the VM.
2898f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
289923ba9600c0207ef406513fce4c0278796e0b9415Elliott Hughesstatic jint DetachCurrentThread(JavaVM* vm) {
2900f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Thread* self = dvmThreadSelf();
290123ba9600c0207ef406513fce4c0278796e0b9415Elliott Hughes    if (self == NULL) {
290223ba9600c0207ef406513fce4c0278796e0b9415Elliott Hughes        /* not attached, can't do anything */
2903f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return JNI_ERR;
290423ba9600c0207ef406513fce4c0278796e0b9415Elliott Hughes    }
2905f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2906f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* switch to "running" to check for suspension */
2907f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmChangeStatus(self, THREAD_RUNNING);
2908f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2909f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* detach the thread */
2910f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmDetachCurrentThread();
2911f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2912f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* (no need to change status back -- we have no status) */
2913f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return JNI_OK;
2914f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
2915f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2916f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
2917f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * If current thread is attached to VM, return the associated JNIEnv.
2918f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Otherwise, stuff NULL in and return JNI_EDETACHED.
2919f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
2920f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * JVMTI overloads this by specifying a magic value for "version", so we
2921f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * do want to check that here.
2922f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
292323ba9600c0207ef406513fce4c0278796e0b9415Elliott Hughesstatic jint GetEnv(JavaVM* vm, void** env, jint version) {
2924f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Thread* self = dvmThreadSelf();
2925f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
292623ba9600c0207ef406513fce4c0278796e0b9415Elliott Hughes    if (version < JNI_VERSION_1_1 || version > JNI_VERSION_1_6) {
2927f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return JNI_EVERSION;
292823ba9600c0207ef406513fce4c0278796e0b9415Elliott Hughes    }
2929f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2930f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (self == NULL) {
2931f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        *env = NULL;
2932f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
2933f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* TODO: status change is probably unnecessary */
2934f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmChangeStatus(self, THREAD_RUNNING);
2935f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        *env = (void*) dvmGetThreadJNIEnv(self);
2936f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmChangeStatus(self, THREAD_NATIVE);
2937f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
293823ba9600c0207ef406513fce4c0278796e0b9415Elliott Hughes    return (*env != NULL) ? JNI_OK : JNI_EDETACHED;
2939f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
2940f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2941f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
2942f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Destroy the VM.  This may be called from any thread.
2943f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
2944f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * If the current thread is attached, wait until the current thread is
2945f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the only non-daemon user-level thread.  If the current thread is not
2946f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * attached, we attach it and do the processing as usual.  (If the attach
2947f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * fails, it's probably because all the non-daemon threads have already
2948f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * exited and the VM doesn't want to let us back in.)
2949f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
2950f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * TODO: we don't really deal with the situation where more than one thread
2951f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * has called here.  One thread wins, the other stays trapped waiting on
2952f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the condition variable forever.  Not sure this situation is interesting
2953f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * in real life.
2954f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
295523ba9600c0207ef406513fce4c0278796e0b9415Elliott Hughesstatic jint DestroyJavaVM(JavaVM* vm) {
2956f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    JavaVMExt* ext = (JavaVMExt*) vm;
295723ba9600c0207ef406513fce4c0278796e0b9415Elliott Hughes    if (ext == NULL) {
2958f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return JNI_ERR;
295923ba9600c0207ef406513fce4c0278796e0b9415Elliott Hughes    }
2960f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
296123ba9600c0207ef406513fce4c0278796e0b9415Elliott Hughes    if (gDvm.verboseShutdown) {
2962062bf509a77fce9dfcb7e7b2e401cf2a124d83d5Steve Block        ALOGD("DestroyJavaVM waiting for non-daemon threads to exit");
296323ba9600c0207ef406513fce4c0278796e0b9415Elliott Hughes    }
2964f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2965f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
2966f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Sleep on a condition variable until it's okay to exit.
2967f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
296823ba9600c0207ef406513fce4c0278796e0b9415Elliott Hughes    Thread* self = dvmThreadSelf();
2969f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (self == NULL) {
2970f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        JNIEnv* tmpEnv;
2971f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (AttachCurrentThread(vm, &tmpEnv, NULL) != JNI_OK) {
297292c1f6f1b4249e4e379452ee7b49f027052bf4ceSteve Block            ALOGV("Unable to reattach main for Destroy; assuming VM is shutting down (count=%d)",
2973f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                gDvm.nonDaemonThreadCount);
2974f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            goto shutdown;
2975f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
297692c1f6f1b4249e4e379452ee7b49f027052bf4ceSteve Block            ALOGV("Attached to wait for shutdown in Destroy");
2977f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2978f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2979f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmChangeStatus(self, THREAD_VMWAIT);
2980f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2981f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmLockThreadList(self);
2982f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    gDvm.nonDaemonThreadCount--;    // remove current thread from count
2983f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
298423ba9600c0207ef406513fce4c0278796e0b9415Elliott Hughes    while (gDvm.nonDaemonThreadCount > 0) {
2985f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        pthread_cond_wait(&gDvm.vmExitCond, &gDvm.threadListLock);
298623ba9600c0207ef406513fce4c0278796e0b9415Elliott Hughes    }
2987f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2988f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmUnlockThreadList();
2989f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    self = NULL;
2990f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2991f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectshutdown:
2992f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    // TODO: call System.exit() to run any registered shutdown hooks
2993f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    // (this may not return -- figure out how this should work)
2994f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
299523ba9600c0207ef406513fce4c0278796e0b9415Elliott Hughes    if (gDvm.verboseShutdown) {
2996062bf509a77fce9dfcb7e7b2e401cf2a124d83d5Steve Block        ALOGD("DestroyJavaVM shutting VM down");
299723ba9600c0207ef406513fce4c0278796e0b9415Elliott Hughes    }
2998f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmShutdown();
2999f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3000f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    // TODO - free resources associated with JNI-attached daemon threads
3001f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    free(ext->envList);
3002f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    free(ext);
3003f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3004f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return JNI_OK;
3005f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
3006f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3007f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3008f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
3009f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * ===========================================================================
3010f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *      Function tables
3011f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * ===========================================================================
3012f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
3013f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3014f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic const struct JNINativeInterface gNativeInterface = {
3015f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    NULL,
3016f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    NULL,
3017f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    NULL,
3018f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    NULL,
3019f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3020f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    GetVersion,
3021f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3022f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    DefineClass,
3023f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    FindClass,
3024f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3025f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    FromReflectedMethod,
3026f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    FromReflectedField,
3027f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ToReflectedMethod,
3028f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3029f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    GetSuperclass,
3030f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    IsAssignableFrom,
3031f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3032f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ToReflectedField,
3033f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3034f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Throw,
3035f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ThrowNew,
3036f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ExceptionOccurred,
3037f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ExceptionDescribe,
3038f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ExceptionClear,
3039f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    FatalError,
3040f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3041f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    PushLocalFrame,
3042f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    PopLocalFrame,
3043f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3044f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    NewGlobalRef,
3045f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    DeleteGlobalRef,
3046f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    DeleteLocalRef,
3047f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    IsSameObject,
3048f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    NewLocalRef,
3049f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    EnsureLocalCapacity,
3050f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3051f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    AllocObject,
3052f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    NewObject,
3053f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    NewObjectV,
3054f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    NewObjectA,
3055f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3056f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    GetObjectClass,
3057f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    IsInstanceOf,
3058f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3059f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    GetMethodID,
3060f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3061f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    CallObjectMethod,
3062f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    CallObjectMethodV,
3063f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    CallObjectMethodA,
3064f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    CallBooleanMethod,
3065f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    CallBooleanMethodV,
3066f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    CallBooleanMethodA,
3067f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    CallByteMethod,
3068f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    CallByteMethodV,
3069f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    CallByteMethodA,
3070f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    CallCharMethod,
3071f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    CallCharMethodV,
3072f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    CallCharMethodA,
3073f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    CallShortMethod,
3074f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    CallShortMethodV,
3075f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    CallShortMethodA,
3076f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    CallIntMethod,
3077f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    CallIntMethodV,
3078f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    CallIntMethodA,
3079f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    CallLongMethod,
3080f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    CallLongMethodV,
3081f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    CallLongMethodA,
3082f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    CallFloatMethod,
3083f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    CallFloatMethodV,
3084f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    CallFloatMethodA,
3085f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    CallDoubleMethod,
3086f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    CallDoubleMethodV,
3087f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    CallDoubleMethodA,
3088f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    CallVoidMethod,
3089f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    CallVoidMethodV,
3090f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    CallVoidMethodA,
3091f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3092f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    CallNonvirtualObjectMethod,
3093f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    CallNonvirtualObjectMethodV,
3094f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    CallNonvirtualObjectMethodA,
3095f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    CallNonvirtualBooleanMethod,
3096f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    CallNonvirtualBooleanMethodV,
3097f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    CallNonvirtualBooleanMethodA,
3098f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    CallNonvirtualByteMethod,
3099f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    CallNonvirtualByteMethodV,
3100f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    CallNonvirtualByteMethodA,
3101f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    CallNonvirtualCharMethod,
3102f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    CallNonvirtualCharMethodV,
3103f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    CallNonvirtualCharMethodA,
3104f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    CallNonvirtualShortMethod,
3105f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    CallNonvirtualShortMethodV,
3106f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    CallNonvirtualShortMethodA,
3107f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    CallNonvirtualIntMethod,
3108f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    CallNonvirtualIntMethodV,
3109f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    CallNonvirtualIntMethodA,
3110f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    CallNonvirtualLongMethod,
3111f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    CallNonvirtualLongMethodV,
3112f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    CallNonvirtualLongMethodA,
3113f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    CallNonvirtualFloatMethod,
3114f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    CallNonvirtualFloatMethodV,
3115f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    CallNonvirtualFloatMethodA,
3116f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    CallNonvirtualDoubleMethod,
3117f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    CallNonvirtualDoubleMethodV,
3118f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    CallNonvirtualDoubleMethodA,
3119f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    CallNonvirtualVoidMethod,
3120f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    CallNonvirtualVoidMethodV,
3121f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    CallNonvirtualVoidMethodA,
3122f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3123f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    GetFieldID,
3124f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3125f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    GetObjectField,
3126f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    GetBooleanField,
3127f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    GetByteField,
3128f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    GetCharField,
3129f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    GetShortField,
3130f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    GetIntField,
3131f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    GetLongField,
3132f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    GetFloatField,
3133f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    GetDoubleField,
3134f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    SetObjectField,
3135f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    SetBooleanField,
3136f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    SetByteField,
3137f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    SetCharField,
3138f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    SetShortField,
3139f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    SetIntField,
3140f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    SetLongField,
3141f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    SetFloatField,
3142f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    SetDoubleField,
3143f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3144f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    GetStaticMethodID,
3145f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3146f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    CallStaticObjectMethod,
3147f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    CallStaticObjectMethodV,
3148f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    CallStaticObjectMethodA,
3149f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    CallStaticBooleanMethod,
3150f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    CallStaticBooleanMethodV,
3151f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    CallStaticBooleanMethodA,
3152f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    CallStaticByteMethod,
3153f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    CallStaticByteMethodV,
3154f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    CallStaticByteMethodA,
3155f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    CallStaticCharMethod,
3156f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    CallStaticCharMethodV,
3157f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    CallStaticCharMethodA,
3158f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    CallStaticShortMethod,
3159f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    CallStaticShortMethodV,
3160f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    CallStaticShortMethodA,
3161f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    CallStaticIntMethod,
3162f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    CallStaticIntMethodV,
3163f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    CallStaticIntMethodA,
3164f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    CallStaticLongMethod,
3165f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    CallStaticLongMethodV,
3166f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    CallStaticLongMethodA,
3167f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    CallStaticFloatMethod,
3168f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    CallStaticFloatMethodV,
3169f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    CallStaticFloatMethodA,
3170f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    CallStaticDoubleMethod,
3171f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    CallStaticDoubleMethodV,
3172f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    CallStaticDoubleMethodA,
3173f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    CallStaticVoidMethod,
3174f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    CallStaticVoidMethodV,
3175f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    CallStaticVoidMethodA,
3176f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3177f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    GetStaticFieldID,
3178f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3179f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    GetStaticObjectField,
3180f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    GetStaticBooleanField,
3181f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    GetStaticByteField,
3182f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    GetStaticCharField,
3183f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    GetStaticShortField,
3184f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    GetStaticIntField,
3185f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    GetStaticLongField,
3186f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    GetStaticFloatField,
3187f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    GetStaticDoubleField,
3188f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3189f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    SetStaticObjectField,
3190f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    SetStaticBooleanField,
3191f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    SetStaticByteField,
3192f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    SetStaticCharField,
3193f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    SetStaticShortField,
3194f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    SetStaticIntField,
3195f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    SetStaticLongField,
3196f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    SetStaticFloatField,
3197f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    SetStaticDoubleField,
3198f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3199f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    NewString,
3200f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3201f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    GetStringLength,
3202f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    GetStringChars,
3203f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ReleaseStringChars,
3204f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3205f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    NewStringUTF,
3206f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    GetStringUTFLength,
3207f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    GetStringUTFChars,
3208f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ReleaseStringUTFChars,
3209f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3210f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    GetArrayLength,
3211f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    NewObjectArray,
3212f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    GetObjectArrayElement,
3213f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    SetObjectArrayElement,
3214f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3215f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    NewBooleanArray,
3216f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    NewByteArray,
3217f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    NewCharArray,
3218f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    NewShortArray,
3219f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    NewIntArray,
3220f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    NewLongArray,
3221f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    NewFloatArray,
3222f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    NewDoubleArray,
3223f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3224f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    GetBooleanArrayElements,
3225f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    GetByteArrayElements,
3226f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    GetCharArrayElements,
3227f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    GetShortArrayElements,
3228f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    GetIntArrayElements,
3229f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    GetLongArrayElements,
3230f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    GetFloatArrayElements,
3231f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    GetDoubleArrayElements,
3232f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3233f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ReleaseBooleanArrayElements,
3234f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ReleaseByteArrayElements,
3235f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ReleaseCharArrayElements,
3236f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ReleaseShortArrayElements,
3237f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ReleaseIntArrayElements,
3238f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ReleaseLongArrayElements,
3239f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ReleaseFloatArrayElements,
3240f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ReleaseDoubleArrayElements,
3241f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3242f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    GetBooleanArrayRegion,
3243f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    GetByteArrayRegion,
3244f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    GetCharArrayRegion,
3245f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    GetShortArrayRegion,
3246f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    GetIntArrayRegion,
3247f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    GetLongArrayRegion,
3248f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    GetFloatArrayRegion,
3249f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    GetDoubleArrayRegion,
3250f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    SetBooleanArrayRegion,
3251f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    SetByteArrayRegion,
3252f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    SetCharArrayRegion,
3253f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    SetShortArrayRegion,
3254f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    SetIntArrayRegion,
3255f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    SetLongArrayRegion,
3256f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    SetFloatArrayRegion,
3257f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    SetDoubleArrayRegion,
3258f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3259f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    RegisterNatives,
3260f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    UnregisterNatives,
3261f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3262f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    MonitorEnter,
3263f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    MonitorExit,
3264f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3265f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    GetJavaVM,
3266f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3267f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    GetStringRegion,
3268f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    GetStringUTFRegion,
3269f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3270f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    GetPrimitiveArrayCritical,
3271f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ReleasePrimitiveArrayCritical,
3272f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3273f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    GetStringCritical,
3274f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ReleaseStringCritical,
3275f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3276f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    NewWeakGlobalRef,
3277f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    DeleteWeakGlobalRef,
3278f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3279f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ExceptionCheck,
3280f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3281f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    NewDirectByteBuffer,
3282f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    GetDirectBufferAddress,
3283f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    GetDirectBufferCapacity,
3284f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3285f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    GetObjectRefType
3286f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project};
328723ba9600c0207ef406513fce4c0278796e0b9415Elliott Hughes
3288f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic const struct JNIInvokeInterface gInvokeInterface = {
3289f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    NULL,
3290f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    NULL,
3291f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    NULL,
3292f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3293f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    DestroyJavaVM,
3294f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    AttachCurrentThread,
3295f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    DetachCurrentThread,
3296f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3297f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    GetEnv,
3298f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3299f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    AttachCurrentThreadAsDaemon,
3300f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project};
3301f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3302f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
3303f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * ===========================================================================
3304f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *      VM/Env creation
3305f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * ===========================================================================
3306f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
3307f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3308f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
33090647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes * Create a new JNIEnv struct and add it to the VM's list.
33100647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes *
33110647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes * "self" will be NULL for the main thread, since the VM hasn't started
33120647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes * yet; the value will be filled in later.
33130647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes */
33140647d294bab9312be67a9032adfa4f0b9ba0984aElliott HughesJNIEnv* dvmCreateJNIEnv(Thread* self) {
3315d5c80e06a771bb34336c1ec5b0d9ce8a47ec4244Elliott Hughes    JavaVMExt* vm = (JavaVMExt*) gDvmJni.jniVm;
33160647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes
33170647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    //if (self != NULL)
33184308417beec548c2b2c06ecec4f7f4a965b09fb2Steve Block    //    ALOGI("Ent CreateJNIEnv: threadid=%d %p", self->threadId, self);
33190647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes
33200647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    assert(vm != NULL);
33210647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes
332223ba9600c0207ef406513fce4c0278796e0b9415Elliott Hughes    JNIEnvExt* newEnv = (JNIEnvExt*) calloc(1, sizeof(JNIEnvExt));
33230647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    newEnv->funcTable = &gNativeInterface;
33240647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    if (self != NULL) {
33250647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes        dvmSetJniEnvThreadId((JNIEnv*) newEnv, self);
33260647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes        assert(newEnv->envThreadId != 0);
33270647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    } else {
33280647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes        /* make it obvious if we fail to initialize these later */
33290647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes        newEnv->envThreadId = 0x77777775;
33300647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes        newEnv->self = (Thread*) 0x77777779;
33310647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    }
3332a5f3ed80b3b058b006ee2b09915d1400cebd0442Elliott Hughes    if (gDvmJni.useCheckJni) {
33330647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes        dvmUseCheckedJniEnv(newEnv);
33340647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    }
33350647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes
333689383030aca8f77aeab73540404ba332ce5ac035Elliott Hughes    ScopedPthreadMutexLock lock(&vm->envListLock);
33370647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes
33380647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    /* insert at head of list */
33390647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    newEnv->next = vm->envList;
33400647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    assert(newEnv->prev == NULL);
33410647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    if (vm->envList == NULL) {
33420647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes        // rare, but possible
33430647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes        vm->envList = newEnv;
33440647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    } else {
33450647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes        vm->envList->prev = newEnv;
33460647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    }
33470647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    vm->envList = newEnv;
33480647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes
33490647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    //if (self != NULL)
33504308417beec548c2b2c06ecec4f7f4a965b09fb2Steve Block    //    ALOGI("Xit CreateJNIEnv: threadid=%d %p", self->threadId, self);
33510647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    return (JNIEnv*) newEnv;
33520647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes}
33530647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes
33540647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes/*
33550647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes * Remove a JNIEnv struct from the list and free it.
33560647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes */
33570647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughesvoid dvmDestroyJNIEnv(JNIEnv* env) {
33580647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    if (env == NULL) {
33590647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes        return;
33600647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    }
33610647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes
33624308417beec548c2b2c06ecec4f7f4a965b09fb2Steve Block    //ALOGI("Ent DestroyJNIEnv: threadid=%d %p", self->threadId, self);
33630647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes
33640647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    JNIEnvExt* extEnv = (JNIEnvExt*) env;
3365d5c80e06a771bb34336c1ec5b0d9ce8a47ec4244Elliott Hughes    JavaVMExt* vm = (JavaVMExt*) gDvmJni.jniVm;
336689383030aca8f77aeab73540404ba332ce5ac035Elliott Hughes
336789383030aca8f77aeab73540404ba332ce5ac035Elliott Hughes    ScopedPthreadMutexLock lock(&vm->envListLock);
33680647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes
33690647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    if (extEnv == vm->envList) {
33700647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes        assert(extEnv->prev == NULL);
33710647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes        vm->envList = extEnv->next;
33720647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    } else {
33730647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes        assert(extEnv->prev != NULL);
33740647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes        extEnv->prev->next = extEnv->next;
33750647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    }
33760647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    if (extEnv->next != NULL) {
33770647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes        extEnv->next->prev = extEnv->prev;
33780647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    }
33790647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes
33800647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes    free(env);
33814308417beec548c2b2c06ecec4f7f4a965b09fb2Steve Block    //ALOGI("Xit DestroyJNIEnv: threadid=%d %p", self->threadId, self);
33820647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes}
33830647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes
33840647d294bab9312be67a9032adfa4f0b9ba0984aElliott Hughes/*
3385f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Enable "checked JNI" after the VM has partially started.  This must
3386f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * only be called in "zygote" mode, when we have one thread running.
338759b6177e2fa9c9f1f16d7eff57e481f5282afbdaAndy McFadden *
338859b6177e2fa9c9f1f16d7eff57e481f5282afbdaAndy McFadden * This doesn't attempt to rewrite the JNI call bridge associated with
338959b6177e2fa9c9f1f16d7eff57e481f5282afbdaAndy McFadden * native methods, so we won't get those checks for any methods that have
339059b6177e2fa9c9f1f16d7eff57e481f5282afbdaAndy McFadden * already been resolved.
3391f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
339223ba9600c0207ef406513fce4c0278796e0b9415Elliott Hughesvoid dvmLateEnableCheckedJni() {
339323ba9600c0207ef406513fce4c0278796e0b9415Elliott Hughes    JNIEnvExt* extEnv = dvmGetJNIEnvForThread();
3394f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (extEnv == NULL) {
3395c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block        ALOGE("dvmLateEnableCheckedJni: thread has no JNIEnv");
3396f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return;
3397f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
3398d5c80e06a771bb34336c1ec5b0d9ce8a47ec4244Elliott Hughes    JavaVMExt* extVm = (JavaVMExt*) gDvmJni.jniVm;
3399f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(extVm != NULL);
3400f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3401a5f3ed80b3b058b006ee2b09915d1400cebd0442Elliott Hughes    if (!gDvmJni.useCheckJni) {
3402062bf509a77fce9dfcb7e7b2e401cf2a124d83d5Steve Block        ALOGD("Late-enabling CheckJNI");
3403f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmUseCheckedJniVm(extVm);
3404f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmUseCheckedJniEnv(extEnv);
3405f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
3406062bf509a77fce9dfcb7e7b2e401cf2a124d83d5Steve Block        ALOGD("Not late-enabling CheckJNI (already on)");
3407f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
3408f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
3409f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3410f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
3411f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Not supported.
3412f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
341323ba9600c0207ef406513fce4c0278796e0b9415Elliott Hughesjint JNI_GetDefaultJavaVMInitArgs(void* vm_args) {
3414f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return JNI_ERR;
3415f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
3416f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3417f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
3418f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Return a buffer full of created VMs.
3419f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
3420f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We always have zero or one.
3421f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
342223ba9600c0207ef406513fce4c0278796e0b9415Elliott Hughesjint JNI_GetCreatedJavaVMs(JavaVM** vmBuf, jsize bufLen, jsize* nVMs) {
3423d5c80e06a771bb34336c1ec5b0d9ce8a47ec4244Elliott Hughes    if (gDvmJni.jniVm != NULL) {
3424f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        *nVMs = 1;
342523ba9600c0207ef406513fce4c0278796e0b9415Elliott Hughes        if (bufLen > 0) {
3426d5c80e06a771bb34336c1ec5b0d9ce8a47ec4244Elliott Hughes            *vmBuf++ = gDvmJni.jniVm;
342723ba9600c0207ef406513fce4c0278796e0b9415Elliott Hughes        }
3428f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
3429f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        *nVMs = 0;
3430f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
3431f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return JNI_OK;
3432f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
3433f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3434f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
3435f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Create a new VM instance.
3436f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
3437f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The current thread becomes the main VM thread.  We return immediately,
3438f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * which effectively means the caller is executing in a native method.
3439f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
344023ba9600c0207ef406513fce4c0278796e0b9415Elliott Hughesjint JNI_CreateJavaVM(JavaVM** p_vm, JNIEnv** p_env, void* vm_args) {
3441f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const JavaVMInitArgs* args = (JavaVMInitArgs*) vm_args;
344223ba9600c0207ef406513fce4c0278796e0b9415Elliott Hughes    if (args->version < JNI_VERSION_1_2) {
3443f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return JNI_EVERSION;
344423ba9600c0207ef406513fce4c0278796e0b9415Elliott Hughes    }
3445f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3446f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    // TODO: don't allow creation of multiple VMs -- one per customer for now
3447f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3448f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* zero globals; not strictly necessary the first time a VM is started */
3449f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    memset(&gDvm, 0, sizeof(gDvm));
3450f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3451f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
3452f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Set up structures for JNIEnv and VM.
3453f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
3454b74e7190e86d559712747e5cdb31a0d390b7af7dIliyan Malchev    JavaVMExt* pVM = (JavaVMExt*) calloc(1, sizeof(JavaVMExt));
3455f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    pVM->funcTable = &gInvokeInterface;
3456a5f3ed80b3b058b006ee2b09915d1400cebd0442Elliott Hughes    pVM->envList = NULL;
3457f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmInitMutex(&pVM->envListLock);
3458f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3459a5f3ed80b3b058b006ee2b09915d1400cebd0442Elliott Hughes    UniquePtr<const char*[]> argv(new const char*[args->nOptions]);
3460a5f3ed80b3b058b006ee2b09915d1400cebd0442Elliott Hughes    memset(argv.get(), 0, sizeof(char*) * (args->nOptions));
3461f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3462f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
3463f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Convert JNI args to argv.
3464f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
3465f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * We have to pull out vfprintf/exit/abort, because they use the
3466f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * "extraInfo" field to pass function pointer "hooks" in.  We also
3467f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * look for the -Xcheck:jni stuff here.
3468f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
3469d5c80e06a771bb34336c1ec5b0d9ce8a47ec4244Elliott Hughes    int argc = 0;
3470a5f3ed80b3b058b006ee2b09915d1400cebd0442Elliott Hughes    for (int i = 0; i < args->nOptions; i++) {
3471f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        const char* optStr = args->options[i].optionString;
3472f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (optStr == NULL) {
3473a5f3ed80b3b058b006ee2b09915d1400cebd0442Elliott Hughes            dvmFprintf(stderr, "ERROR: CreateJavaVM failed: argument %d was NULL\n", i);
3474a5f3ed80b3b058b006ee2b09915d1400cebd0442Elliott Hughes            return JNI_ERR;
3475f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else if (strcmp(optStr, "vfprintf") == 0) {
3476d5c80e06a771bb34336c1ec5b0d9ce8a47ec4244Elliott Hughes            gDvm.vfprintfHook = (int (*)(FILE *, const char*, va_list))args->options[i].extraInfo;
3477f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else if (strcmp(optStr, "exit") == 0) {
3478fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro            gDvm.exitHook = (void (*)(int)) args->options[i].extraInfo;
3479f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else if (strcmp(optStr, "abort") == 0) {
3480fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro            gDvm.abortHook = (void (*)(void))args->options[i].extraInfo;
34813b55675a442a173eb1337ba3c5866cd30cefb504Brad Fitzpatrick        } else if (strcmp(optStr, "sensitiveThread") == 0) {
3482824290c8a9102db31f3fb69fc530ebb3d8462d71Brad Fitzpatrick            gDvm.isSensitiveThreadHook = (bool (*)(void))args->options[i].extraInfo;
3483f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else if (strcmp(optStr, "-Xcheck:jni") == 0) {
3484a5f3ed80b3b058b006ee2b09915d1400cebd0442Elliott Hughes            gDvmJni.useCheckJni = true;
3485f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else if (strncmp(optStr, "-Xjniopts:", 10) == 0) {
3486d5c80e06a771bb34336c1ec5b0d9ce8a47ec4244Elliott Hughes            char* jniOpts = strdup(optStr + 10);
3487d5c80e06a771bb34336c1ec5b0d9ce8a47ec4244Elliott Hughes            size_t jniOptCount = 1;
3488d5c80e06a771bb34336c1ec5b0d9ce8a47ec4244Elliott Hughes            for (char* p = jniOpts; *p != 0; ++p) {
3489d5c80e06a771bb34336c1ec5b0d9ce8a47ec4244Elliott Hughes                if (*p == ',') {
3490d5c80e06a771bb34336c1ec5b0d9ce8a47ec4244Elliott Hughes                    ++jniOptCount;
3491d5c80e06a771bb34336c1ec5b0d9ce8a47ec4244Elliott Hughes                    *p = 0;
3492d5c80e06a771bb34336c1ec5b0d9ce8a47ec4244Elliott Hughes                }
3493d5c80e06a771bb34336c1ec5b0d9ce8a47ec4244Elliott Hughes            }
3494d5c80e06a771bb34336c1ec5b0d9ce8a47ec4244Elliott Hughes            char* jniOpt = jniOpts;
3495d5c80e06a771bb34336c1ec5b0d9ce8a47ec4244Elliott Hughes            for (size_t i = 0; i < jniOptCount; ++i) {
3496d5c80e06a771bb34336c1ec5b0d9ce8a47ec4244Elliott Hughes                if (strcmp(jniOpt, "warnonly") == 0) {
3497a5f3ed80b3b058b006ee2b09915d1400cebd0442Elliott Hughes                    gDvmJni.warnOnly = true;
3498d5c80e06a771bb34336c1ec5b0d9ce8a47ec4244Elliott Hughes                } else if (strcmp(jniOpt, "forcecopy") == 0) {
3499d5c80e06a771bb34336c1ec5b0d9ce8a47ec4244Elliott Hughes                    gDvmJni.forceCopy = true;
35003f04fa049734772a945243d64d6ce9a34b39b730Elliott Hughes                } else if (strcmp(jniOpt, "logThirdPartyJni") == 0) {
35013f04fa049734772a945243d64d6ce9a34b39b730Elliott Hughes                    gDvmJni.logThirdPartyJni = true;
3502f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                } else {
3503d5c80e06a771bb34336c1ec5b0d9ce8a47ec4244Elliott Hughes                    dvmFprintf(stderr, "ERROR: CreateJavaVM failed: unknown -Xjniopts option '%s'\n",
3504d5c80e06a771bb34336c1ec5b0d9ce8a47ec4244Elliott Hughes                            jniOpt);
3505d5c80e06a771bb34336c1ec5b0d9ce8a47ec4244Elliott Hughes                    return JNI_ERR;
3506f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
3507d5c80e06a771bb34336c1ec5b0d9ce8a47ec4244Elliott Hughes                jniOpt += strlen(jniOpt) + 1;
3508f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
3509d5c80e06a771bb34336c1ec5b0d9ce8a47ec4244Elliott Hughes            free(jniOpts);
3510f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
3511f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* regular option */
3512d5c80e06a771bb34336c1ec5b0d9ce8a47ec4244Elliott Hughes            argv[argc++] = optStr;
3513f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
3514f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
3515f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3516a5f3ed80b3b058b006ee2b09915d1400cebd0442Elliott Hughes    if (gDvmJni.useCheckJni) {
3517f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmUseCheckedJniVm(pVM);
3518f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
3519f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3520d5c80e06a771bb34336c1ec5b0d9ce8a47ec4244Elliott Hughes    if (gDvmJni.jniVm != NULL) {
3521d5c80e06a771bb34336c1ec5b0d9ce8a47ec4244Elliott Hughes        dvmFprintf(stderr, "ERROR: Dalvik only supports one VM per process\n");
3522d5c80e06a771bb34336c1ec5b0d9ce8a47ec4244Elliott Hughes        return JNI_ERR;
3523d5c80e06a771bb34336c1ec5b0d9ce8a47ec4244Elliott Hughes    }
3524d5c80e06a771bb34336c1ec5b0d9ce8a47ec4244Elliott Hughes    gDvmJni.jniVm = (JavaVM*) pVM;
3525f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3526f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
3527d5c80e06a771bb34336c1ec5b0d9ce8a47ec4244Elliott Hughes     * Create a JNIEnv for the main thread.  We need to have something set up
3528f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * here because some of the class initialization we do when starting
3529f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * up the VM will call into native code.
3530f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
3531a5f3ed80b3b058b006ee2b09915d1400cebd0442Elliott Hughes    JNIEnvExt* pEnv = (JNIEnvExt*) dvmCreateJNIEnv(NULL);
3532f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3533a5f3ed80b3b058b006ee2b09915d1400cebd0442Elliott Hughes    /* Initialize VM. */
3534f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    gDvm.initializing = true;
35355719d5c79558ffdbbb863ddcf61836221aba922dElliott Hughes    std::string status =
35365719d5c79558ffdbbb863ddcf61836221aba922dElliott Hughes            dvmStartup(argc, argv.get(), args->ignoreUnrecognized, (JNIEnv*)pEnv);
3537a5f3ed80b3b058b006ee2b09915d1400cebd0442Elliott Hughes    gDvm.initializing = false;
3538a5f3ed80b3b058b006ee2b09915d1400cebd0442Elliott Hughes
35395719d5c79558ffdbbb863ddcf61836221aba922dElliott Hughes    if (!status.empty()) {
3540f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        free(pEnv);
3541f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        free(pVM);
3542e8e1ddccd616e8226b7cc1e4e9fdb327429249e8Steve Block        ALOGW("CreateJavaVM failed: %s", status.c_str());
3543a5f3ed80b3b058b006ee2b09915d1400cebd0442Elliott Hughes        return JNI_ERR;
3544f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
3545f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3546f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
3547f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Success!  Return stuff to caller.
3548f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
3549f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmChangeStatus(NULL, THREAD_NATIVE);
3550f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    *p_env = (JNIEnv*) pEnv;
3551f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    *p_vm = (JavaVM*) pVM;
355292c1f6f1b4249e4e379452ee7b49f027052bf4ceSteve Block    ALOGV("CreateJavaVM succeeded");
3553a5f3ed80b3b058b006ee2b09915d1400cebd0442Elliott Hughes    return JNI_OK;
3554f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
3555