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