blob: 19f8abfee077d3143cbd3a82d34010de5d28de41 [file] [log] [blame]
Elliott Hughesa2501992011-08-26 19:39:54 -07001/*
2 * Copyright (C) 2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "jni_internal.h"
18
19#include <sys/mman.h>
20#include <zlib.h>
21
Elliott Hughes07ed66b2012-12-12 18:34:25 -080022#include "base/logging.h"
Elliott Hughesa2501992011-08-26 19:39:54 -070023#include "class_linker.h"
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080024#include "class_linker-inl.h"
Ian Rogers4f6ad8a2013-03-18 15:27:28 -070025#include "dex_file-inl.h"
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080026#include "gc/space.h"
27#include "mirror/class-inl.h"
28#include "mirror/field-inl.h"
29#include "mirror/abstract_method-inl.h"
30#include "mirror/object-inl.h"
31#include "mirror/object_array-inl.h"
32#include "mirror/throwable.h"
Ian Rogers6d4d9fc2011-11-30 16:24:48 -080033#include "object_utils.h"
Jeff Hao58df3272013-04-22 15:28:53 -070034#include "runtime.h"
Ian Rogers00f7d0e2012-07-19 15:28:27 -070035#include "scoped_thread_state_change.h"
Elliott Hughesa2501992011-08-26 19:39:54 -070036#include "thread.h"
37
Elliott Hughese6087632011-09-26 12:18:25 -070038#define LIBCORE_CPP_JNI_HELPERS
39#include <JNIHelp.h> // from libcore
40#undef LIBCORE_CPP_JNI_HELPERS
41
Elliott Hughesa2501992011-08-26 19:39:54 -070042namespace art {
43
Elliott Hughes3f6635a2012-06-19 13:37:49 -070044static void JniAbort(const char* jni_function_name, const char* msg) {
Elliott Hughesa0957642011-09-02 14:27:33 -070045 Thread* self = Thread::Current();
Ian Rogers00f7d0e2012-07-19 15:28:27 -070046 ScopedObjectAccess soa(self);
Ian Rogers62d6c772013-02-27 08:32:07 -080047 mirror::AbstractMethod* current_method = self->GetCurrentMethod(NULL);
Elliott Hughesa2501992011-08-26 19:39:54 -070048
Elliott Hughes3b6baaa2011-10-14 19:13:56 -070049 std::ostringstream os;
Elliott Hughes3f6635a2012-06-19 13:37:49 -070050 os << "JNI DETECTED ERROR IN APPLICATION: " << msg;
Elliott Hughesa2501992011-08-26 19:39:54 -070051
52 if (jni_function_name != NULL) {
Elliott Hughes3f6635a2012-06-19 13:37:49 -070053 os << "\n in call to " << jni_function_name;
Elliott Hughesa2501992011-08-26 19:39:54 -070054 }
Elliott Hughesa0957642011-09-02 14:27:33 -070055 // TODO: is this useful given that we're about to dump the calling thread's stack?
56 if (current_method != NULL) {
Elliott Hughes3f6635a2012-06-19 13:37:49 -070057 os << "\n from " << PrettyMethod(current_method);
Elliott Hughesa0957642011-09-02 14:27:33 -070058 }
59 os << "\n";
60 self->Dump(os);
Elliott Hughesa2501992011-08-26 19:39:54 -070061
62 JavaVMExt* vm = Runtime::Current()->GetJavaVM();
63 if (vm->check_jni_abort_hook != NULL) {
Elliott Hughesb264f082012-04-06 17:10:10 -070064 vm->check_jni_abort_hook(vm->check_jni_abort_hook_data, os.str());
Elliott Hughesa2501992011-08-26 19:39:54 -070065 } else {
Ian Rogers9da7f592012-08-20 17:14:28 -070066 // Ensure that we get a native stack trace for this thread.
67 self->TransitionFromRunnableToSuspended(kNative);
Elliott Hughesa2501992011-08-26 19:39:54 -070068 LOG(FATAL) << os.str();
Ian Rogers9da7f592012-08-20 17:14:28 -070069 self->TransitionFromSuspendedToRunnable(); // Unreachable, keep annotalysis happy.
Elliott Hughesa2501992011-08-26 19:39:54 -070070 }
71}
72
Elliott Hughes3f6635a2012-06-19 13:37:49 -070073static void JniAbortV(const char* jni_function_name, const char* fmt, va_list ap) {
74 std::string msg;
75 StringAppendV(&msg, fmt, ap);
76 JniAbort(jni_function_name, msg.c_str());
77}
78
79void JniAbortF(const char* jni_function_name, const char* fmt, ...) {
80 va_list args;
81 va_start(args, fmt);
82 JniAbortV(jni_function_name, fmt, args);
83 va_end(args);
84}
85
Elliott Hughesa2501992011-08-26 19:39:54 -070086/*
87 * ===========================================================================
88 * JNI function helpers
89 * ===========================================================================
90 */
91
Ian Rogers959f8ed2012-02-07 16:33:37 -080092static bool IsSirtLocalRef(JNIEnv* env, jobject localRef) {
93 return GetIndirectRefKind(localRef) == kSirtOrInvalid &&
Ian Rogers0399dde2012-06-06 17:09:28 -070094 reinterpret_cast<JNIEnvExt*>(env)->self->SirtContains(localRef);
Ian Rogers959f8ed2012-02-07 16:33:37 -080095}
96
Elliott Hughes3f6635a2012-06-19 13:37:49 -070097// Hack to allow forcecopy to work with jniGetNonMovableArrayElements.
98// The code deliberately uses an invalid sequence of operations, so we
99// need to pass it through unmodified. Review that code before making
100// any changes here.
Elliott Hughesa2501992011-08-26 19:39:54 -0700101#define kNoCopyMagic 0xd5aab57f
102
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700103// Flags passed into ScopedCheck.
Elliott Hughesa2501992011-08-26 19:39:54 -0700104#define kFlag_Default 0x0000
105
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700106#define kFlag_CritBad 0x0000 // Calling while in critical is not allowed.
107#define kFlag_CritOkay 0x0001 // Calling while in critical is allowed.
108#define kFlag_CritGet 0x0002 // This is a critical "get".
109#define kFlag_CritRelease 0x0003 // This is a critical "release".
110#define kFlag_CritMask 0x0003 // Bit mask to get "crit" value.
Elliott Hughesa2501992011-08-26 19:39:54 -0700111
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700112#define kFlag_ExcepBad 0x0000 // Raised exceptions are not allowed.
113#define kFlag_ExcepOkay 0x0004 // Raised exceptions are allowed.
Elliott Hughesa2501992011-08-26 19:39:54 -0700114
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700115#define kFlag_Release 0x0010 // Are we in a non-critical release function?
116#define kFlag_NullableUtf 0x0020 // Are our UTF parameters nullable?
Elliott Hughesa2501992011-08-26 19:39:54 -0700117
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700118#define kFlag_Invocation 0x8000 // Part of the invocation interface (JavaVM*).
Elliott Hughesa2501992011-08-26 19:39:54 -0700119
Elliott Hughes485cac42011-12-09 17:49:35 -0800120#define kFlag_ForceTrace 0x80000000 // Add this to a JNI function's flags if you want to trace every call.
121
Elliott Hughesa0957642011-09-02 14:27:33 -0700122static const char* gBuiltInPrefixes[] = {
123 "Landroid/",
124 "Lcom/android/",
125 "Lcom/google/android/",
126 "Ldalvik/",
127 "Ljava/",
128 "Ljavax/",
129 "Llibcore/",
130 "Lorg/apache/harmony/",
131 NULL
132};
133
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800134static bool ShouldTrace(JavaVMExt* vm, const mirror::AbstractMethod* method)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700135 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Elliott Hughesa0957642011-09-02 14:27:33 -0700136 // If both "-Xcheck:jni" and "-Xjnitrace:" are enabled, we print trace messages
137 // when a native method that matches the -Xjnitrace argument calls a JNI function
138 // such as NewByteArray.
139 // If -verbose:third-party-jni is on, we want to log any JNI function calls
140 // made by a third-party native method.
Elliott Hughes81ff3182012-03-23 20:35:56 -0700141 std::string class_name(MethodHelper(method).GetDeclaringClassDescriptor());
142 if (!vm->trace.empty() && class_name.find(vm->trace) != std::string::npos) {
Elliott Hughesa0957642011-09-02 14:27:33 -0700143 return true;
144 }
Elliott Hughes4dd9b4d2011-12-12 18:29:24 -0800145 if (VLOG_IS_ON(third_party_jni)) {
Elliott Hughesa0957642011-09-02 14:27:33 -0700146 // Return true if we're trying to log all third-party JNI activity and 'method' doesn't look
147 // like part of Android.
Elliott Hughesa0957642011-09-02 14:27:33 -0700148 for (size_t i = 0; gBuiltInPrefixes[i] != NULL; ++i) {
Elliott Hughes81ff3182012-03-23 20:35:56 -0700149 if (StartsWith(class_name, gBuiltInPrefixes[i])) {
Elliott Hughesa0957642011-09-02 14:27:33 -0700150 return false;
151 }
152 }
153 return true;
154 }
155 return false;
156}
157
Elliott Hughesa2501992011-08-26 19:39:54 -0700158class ScopedCheck {
Elliott Hughesba8eee12012-01-24 20:25:24 -0800159 public:
Elliott Hughesa2501992011-08-26 19:39:54 -0700160 // For JNIEnv* functions.
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700161 explicit ScopedCheck(JNIEnv* env, int flags, const char* functionName)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700162 SHARED_LOCK_FUNCTION(Locks::mutator_lock_)
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700163 : soa_(env) {
Ian Rogers365c1022012-06-22 15:05:28 -0700164 Init(flags, functionName, true);
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700165 CheckThread(flags);
Elliott Hughesa2501992011-08-26 19:39:54 -0700166 }
167
168 // For JavaVM* functions.
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700169 // TODO: it's not correct that this is a lock function, but making it so aids annotalysis.
170 explicit ScopedCheck(JavaVM* vm, bool has_method, const char* functionName)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700171 SHARED_LOCK_FUNCTION(Locks::mutator_lock_)
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700172 : soa_(vm) {
Ian Rogers365c1022012-06-22 15:05:28 -0700173 Init(kFlag_Invocation, functionName, has_method);
Elliott Hughesa2501992011-08-26 19:39:54 -0700174 }
175
Ian Rogersb726dcb2012-09-05 08:57:23 -0700176 ~ScopedCheck() UNLOCK_FUNCTION(Locks::mutator_lock_) {}
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700177
178 const ScopedObjectAccess& soa() {
179 return soa_;
180 }
181
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700182 bool ForceCopy() {
Elliott Hughesa2501992011-08-26 19:39:54 -0700183 return Runtime::Current()->GetJavaVM()->force_copy;
184 }
185
Elliott Hughes81ff3182012-03-23 20:35:56 -0700186 // Checks that 'class_name' is a valid "fully-qualified" JNI class name, like "java/lang/Thread"
187 // or "[Ljava/lang/Object;". A ClassLoader can actually normalize class names a couple of
188 // times, so using "java.lang.Thread" instead of "java/lang/Thread" might work in some
189 // circumstances, but this is incorrect.
190 void CheckClassName(const char* class_name) {
191 if (!IsValidJniClassName(class_name)) {
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700192 JniAbortF(function_name_,
193 "illegal class name '%s'\n"
194 " (should be of the form 'package/Class', [Lpackage/Class;' or '[[B')",
195 class_name);
Elliott Hughesa2501992011-08-26 19:39:54 -0700196 }
197 }
198
199 /*
200 * Verify that the field is of the appropriate type. If the field has an
201 * object type, "java_object" is the object we're trying to assign into it.
202 *
203 * Works for both static and instance fields.
204 */
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700205 void CheckFieldType(jobject java_object, jfieldID fid, char prim, bool isStatic)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700206 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800207 mirror::Field* f = CheckFieldID(fid);
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700208 if (f == NULL) {
Elliott Hughesa2501992011-08-26 19:39:54 -0700209 return;
210 }
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800211 mirror::Class* field_type = FieldHelper(f).GetType();
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700212 if (!field_type->IsPrimitive()) {
213 if (java_object != NULL) {
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800214 mirror::Object* obj = soa_.Decode<mirror::Object*>(java_object);
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700215 // If java_object is a weak global ref whose referent has been cleared,
216 // obj will be NULL. Otherwise, obj should always be non-NULL
217 // and valid.
Elliott Hughes88c5c352012-03-15 18:49:48 -0700218 if (!Runtime::Current()->GetHeap()->IsHeapAddress(obj)) {
Mathieu Chartier128c52c2012-10-16 14:12:41 -0700219 Runtime::Current()->GetHeap()->DumpSpaces();
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700220 JniAbortF(function_name_, "field operation on invalid %s: %p",
221 ToStr<IndirectRefKind>(GetIndirectRefKind(java_object)).c_str(), java_object);
Elliott Hughesa2501992011-08-26 19:39:54 -0700222 return;
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700223 } else {
Brian Carlstrom16192862011-09-12 17:50:06 -0700224 if (!obj->InstanceOf(field_type)) {
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700225 JniAbortF(function_name_, "attempt to set field %s with value of wrong type: %s",
226 PrettyField(f).c_str(), PrettyTypeOf(obj).c_str());
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700227 return;
228 }
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700229 }
Elliott Hughesa2501992011-08-26 19:39:54 -0700230 }
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700231 } else if (field_type != Runtime::Current()->GetClassLinker()->FindPrimitiveClass(prim)) {
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700232 JniAbortF(function_name_, "attempt to set field %s with value of wrong type: %c",
233 PrettyField(f).c_str(), prim);
Elliott Hughesa2501992011-08-26 19:39:54 -0700234 return;
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700235 }
236
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700237 if (isStatic != f->IsStatic()) {
Elliott Hughesa2501992011-08-26 19:39:54 -0700238 if (isStatic) {
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700239 JniAbortF(function_name_, "accessing non-static field %s as static", PrettyField(f).c_str());
Elliott Hughesa2501992011-08-26 19:39:54 -0700240 } else {
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700241 JniAbortF(function_name_, "accessing static field %s as non-static", PrettyField(f).c_str());
Elliott Hughesa2501992011-08-26 19:39:54 -0700242 }
Elliott Hughesa2501992011-08-26 19:39:54 -0700243 return;
244 }
245 }
246
247 /*
248 * Verify that this instance field ID is valid for this object.
249 *
250 * Assumes "jobj" has already been validated.
251 */
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700252 void CheckInstanceFieldID(jobject java_object, jfieldID fid)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700253 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800254 mirror::Object* o = soa_.Decode<mirror::Object*>(java_object);
Elliott Hughesb3bd5f02012-03-08 21:05:27 -0800255 if (o == NULL || !Runtime::Current()->GetHeap()->IsHeapAddress(o)) {
Mathieu Chartier128c52c2012-10-16 14:12:41 -0700256 Runtime::Current()->GetHeap()->DumpSpaces();
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700257 JniAbortF(function_name_, "field operation on invalid %s: %p",
258 ToStr<IndirectRefKind>(GetIndirectRefKind(java_object)).c_str(), java_object);
Elliott Hughesa2501992011-08-26 19:39:54 -0700259 return;
260 }
261
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800262 mirror::Field* f = CheckFieldID(fid);
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700263 if (f == NULL) {
264 return;
265 }
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800266 mirror::Class* c = o->GetClass();
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800267 FieldHelper fh(f);
268 if (c->FindInstanceField(fh.GetName(), fh.GetTypeDescriptor()) == NULL) {
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700269 JniAbortF(function_name_, "jfieldID %s not valid for an object of class %s",
270 PrettyField(f).c_str(), PrettyTypeOf(o).c_str());
Elliott Hughesa2501992011-08-26 19:39:54 -0700271 }
272 }
273
274 /*
275 * Verify that the pointer value is non-NULL.
276 */
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700277 void CheckNonNull(const void* ptr) {
Elliott Hughesa2501992011-08-26 19:39:54 -0700278 if (ptr == NULL) {
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700279 JniAbortF(function_name_, "non-nullable argument was NULL");
Elliott Hughesa2501992011-08-26 19:39:54 -0700280 }
281 }
282
283 /*
284 * Verify that the method's return type matches the type of call.
285 * 'expectedType' will be "L" for all objects, including arrays.
286 */
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700287 void CheckSig(jmethodID mid, const char* expectedType, bool isStatic)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700288 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800289 mirror::AbstractMethod* m = CheckMethodID(mid);
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700290 if (m == NULL) {
291 return;
292 }
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800293 if (*expectedType != MethodHelper(m).GetShorty()[0]) {
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700294 JniAbortF(function_name_, "the return type of %s does not match %s",
295 function_name_, PrettyMethod(m).c_str());
296 }
297 if (isStatic != m->IsStatic()) {
Elliott Hughesa2501992011-08-26 19:39:54 -0700298 if (isStatic) {
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700299 JniAbortF(function_name_, "calling non-static method %s with %s",
300 PrettyMethod(m).c_str(), function_name_);
Elliott Hughesa2501992011-08-26 19:39:54 -0700301 } else {
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700302 JniAbortF(function_name_, "calling static method %s with %s",
303 PrettyMethod(m).c_str(), function_name_);
Elliott Hughesa2501992011-08-26 19:39:54 -0700304 }
Elliott Hughesa2501992011-08-26 19:39:54 -0700305 }
306 }
307
308 /*
309 * Verify that this static field ID is valid for this class.
310 *
311 * Assumes "java_class" has already been validated.
312 */
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700313 void CheckStaticFieldID(jclass java_class, jfieldID fid)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700314 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800315 mirror::Class* c = soa_.Decode<mirror::Class*>(java_class);
316 const mirror::Field* f = CheckFieldID(fid);
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700317 if (f == NULL) {
318 return;
319 }
Elliott Hughesa2501992011-08-26 19:39:54 -0700320 if (f->GetDeclaringClass() != c) {
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700321 JniAbortF(function_name_, "static jfieldID %p not valid for class %s",
322 fid, PrettyClass(c).c_str());
Elliott Hughesa2501992011-08-26 19:39:54 -0700323 }
324 }
325
326 /*
Elliott Hughese84278b2012-03-22 10:06:53 -0700327 * Verify that "mid" is appropriate for "java_class".
Elliott Hughesa2501992011-08-26 19:39:54 -0700328 *
329 * A mismatch isn't dangerous, because the jmethodID defines the class. In
Elliott Hughese84278b2012-03-22 10:06:53 -0700330 * fact, java_class is unused in the implementation. It's best if we don't
Elliott Hughesa2501992011-08-26 19:39:54 -0700331 * allow bad code in the system though.
332 *
Elliott Hughese84278b2012-03-22 10:06:53 -0700333 * Instances of "java_class" must be instances of the method's declaring class.
Elliott Hughesa2501992011-08-26 19:39:54 -0700334 */
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700335 void CheckStaticMethod(jclass java_class, jmethodID mid)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700336 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800337 const mirror::AbstractMethod* m = CheckMethodID(mid);
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700338 if (m == NULL) {
339 return;
340 }
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800341 mirror::Class* c = soa_.Decode<mirror::Class*>(java_class);
Elliott Hughesa2501992011-08-26 19:39:54 -0700342 if (!c->IsAssignableFrom(m->GetDeclaringClass())) {
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700343 JniAbortF(function_name_, "can't call static %s on class %s",
344 PrettyMethod(m).c_str(), PrettyClass(c).c_str());
Elliott Hughesa2501992011-08-26 19:39:54 -0700345 }
346 }
347
348 /*
349 * Verify that "mid" is appropriate for "jobj".
350 *
351 * Make sure the object is an instance of the method's declaring class.
352 * (Note the mid might point to a declaration in an interface; this
353 * will be handled automatically by the instanceof check.)
354 */
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700355 void CheckVirtualMethod(jobject java_object, jmethodID mid)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700356 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800357 const mirror::AbstractMethod* m = CheckMethodID(mid);
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700358 if (m == NULL) {
359 return;
360 }
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800361 mirror::Object* o = soa_.Decode<mirror::Object*>(java_object);
Elliott Hughesa2501992011-08-26 19:39:54 -0700362 if (!o->InstanceOf(m->GetDeclaringClass())) {
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700363 JniAbortF(function_name_, "can't call %s on instance of %s",
364 PrettyMethod(m).c_str(), PrettyTypeOf(o).c_str());
Elliott Hughesa2501992011-08-26 19:39:54 -0700365 }
366 }
367
368 /**
369 * The format string is a sequence of the following characters,
370 * and must be followed by arguments of the corresponding types
371 * in the same order.
372 *
373 * Java primitive types:
374 * B - jbyte
375 * C - jchar
376 * D - jdouble
377 * F - jfloat
378 * I - jint
379 * J - jlong
380 * S - jshort
381 * Z - jboolean (shown as true and false)
382 * V - void
383 *
384 * Java reference types:
385 * L - jobject
386 * a - jarray
387 * c - jclass
388 * s - jstring
389 *
390 * JNI types:
391 * b - jboolean (shown as JNI_TRUE and JNI_FALSE)
392 * f - jfieldID
393 * m - jmethodID
394 * p - void*
395 * r - jint (for release mode arguments)
Elliott Hughes78090d12011-10-07 14:31:47 -0700396 * u - const char* (Modified UTF-8)
Elliott Hughesa2501992011-08-26 19:39:54 -0700397 * z - jsize (for lengths; use i if negative values are okay)
398 * v - JavaVM*
399 * E - JNIEnv*
400 * . - no argument; just print "..." (used for varargs JNI calls)
401 *
402 * Use the kFlag_NullableUtf flag where 'u' field(s) are nullable.
403 */
Ian Rogers62d6c772013-02-27 08:32:07 -0800404 void Check(bool entry, const char* fmt0, ...) SHARED_LOCKS_REQUIRED (Locks::mutator_lock_) {
Elliott Hughesa2501992011-08-26 19:39:54 -0700405 va_list ap;
406
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800407 const mirror::AbstractMethod* traceMethod = NULL;
Ian Rogers9365f582013-04-19 09:55:42 -0700408 if (has_method_ && (!soa_.Vm()->trace.empty() || VLOG_IS_ON(third_party_jni))) {
Elliott Hughesa2501992011-08-26 19:39:54 -0700409 // We need to guard some of the invocation interface's calls: a bad caller might
410 // use DetachCurrentThread or GetEnv on a thread that's not yet attached.
Elliott Hughesa0957642011-09-02 14:27:33 -0700411 Thread* self = Thread::Current();
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700412 if ((flags_ & kFlag_Invocation) == 0 || self != NULL) {
Ian Rogers62d6c772013-02-27 08:32:07 -0800413 traceMethod = self->GetCurrentMethod(NULL);
Elliott Hughesa2501992011-08-26 19:39:54 -0700414 }
415 }
Elliott Hughesa0957642011-09-02 14:27:33 -0700416
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700417 if (((flags_ & kFlag_ForceTrace) != 0) || (traceMethod != NULL && ShouldTrace(soa_.Vm(), traceMethod))) {
Elliott Hughesa2501992011-08-26 19:39:54 -0700418 va_start(ap, fmt0);
419 std::string msg;
420 for (const char* fmt = fmt0; *fmt;) {
421 char ch = *fmt++;
422 if (ch == 'B') { // jbyte
423 jbyte b = va_arg(ap, int);
424 if (b >= 0 && b < 10) {
425 StringAppendF(&msg, "%d", b);
426 } else {
427 StringAppendF(&msg, "%#x (%d)", b, b);
428 }
429 } else if (ch == 'C') { // jchar
430 jchar c = va_arg(ap, int);
431 if (c < 0x7f && c >= ' ') {
432 StringAppendF(&msg, "U+%x ('%c')", c, c);
433 } else {
434 StringAppendF(&msg, "U+%x", c);
435 }
436 } else if (ch == 'F' || ch == 'D') { // jfloat, jdouble
437 StringAppendF(&msg, "%g", va_arg(ap, double));
438 } else if (ch == 'I' || ch == 'S') { // jint, jshort
439 StringAppendF(&msg, "%d", va_arg(ap, int));
440 } else if (ch == 'J') { // jlong
441 StringAppendF(&msg, "%lld", va_arg(ap, jlong));
442 } else if (ch == 'Z') { // jboolean
443 StringAppendF(&msg, "%s", va_arg(ap, int) ? "true" : "false");
444 } else if (ch == 'V') { // void
445 msg += "void";
446 } else if (ch == 'v') { // JavaVM*
447 JavaVM* vm = va_arg(ap, JavaVM*);
448 StringAppendF(&msg, "(JavaVM*)%p", vm);
449 } else if (ch == 'E') { // JNIEnv*
450 JNIEnv* env = va_arg(ap, JNIEnv*);
451 StringAppendF(&msg, "(JNIEnv*)%p", env);
452 } else if (ch == 'L' || ch == 'a' || ch == 's') { // jobject, jarray, jstring
453 // For logging purposes, these are identical.
454 jobject o = va_arg(ap, jobject);
455 if (o == NULL) {
456 msg += "NULL";
457 } else {
458 StringAppendF(&msg, "%p", o);
459 }
460 } else if (ch == 'b') { // jboolean (JNI-style)
461 jboolean b = va_arg(ap, int);
462 msg += (b ? "JNI_TRUE" : "JNI_FALSE");
463 } else if (ch == 'c') { // jclass
464 jclass jc = va_arg(ap, jclass);
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800465 mirror::Class* c = reinterpret_cast<mirror::Class*>(Thread::Current()->DecodeJObject(jc));
Elliott Hughesa2501992011-08-26 19:39:54 -0700466 if (c == NULL) {
467 msg += "NULL";
Elliott Hughesb3bd5f02012-03-08 21:05:27 -0800468 } else if (c == kInvalidIndirectRefObject || !Runtime::Current()->GetHeap()->IsHeapAddress(c)) {
Elliott Hughes485cac42011-12-09 17:49:35 -0800469 StringAppendF(&msg, "INVALID POINTER:%p", jc);
470 } else if (!c->IsClass()) {
471 msg += "INVALID NON-CLASS OBJECT OF TYPE:" + PrettyTypeOf(c);
Elliott Hughesa2501992011-08-26 19:39:54 -0700472 } else {
Elliott Hughes54e7df12011-09-16 11:47:04 -0700473 msg += PrettyClass(c);
Elliott Hughesa2501992011-08-26 19:39:54 -0700474 if (!entry) {
475 StringAppendF(&msg, " (%p)", jc);
476 }
477 }
478 } else if (ch == 'f') { // jfieldID
479 jfieldID fid = va_arg(ap, jfieldID);
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800480 mirror::Field* f = reinterpret_cast<mirror::Field*>(fid);
Elliott Hughesa2501992011-08-26 19:39:54 -0700481 msg += PrettyField(f);
482 if (!entry) {
483 StringAppendF(&msg, " (%p)", fid);
484 }
485 } else if (ch == 'z') { // non-negative jsize
486 // You might expect jsize to be size_t, but it's not; it's the same as jint.
487 // We only treat this specially so we can do the non-negative check.
488 // TODO: maybe this wasn't worth it?
489 jint i = va_arg(ap, jint);
490 StringAppendF(&msg, "%d", i);
491 } else if (ch == 'm') { // jmethodID
492 jmethodID mid = va_arg(ap, jmethodID);
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800493 mirror::AbstractMethod* m = reinterpret_cast<mirror::AbstractMethod*>(mid);
Elliott Hughesa2501992011-08-26 19:39:54 -0700494 msg += PrettyMethod(m);
495 if (!entry) {
496 StringAppendF(&msg, " (%p)", mid);
497 }
498 } else if (ch == 'p') { // void* ("pointer")
499 void* p = va_arg(ap, void*);
500 if (p == NULL) {
501 msg += "NULL";
502 } else {
503 StringAppendF(&msg, "(void*) %p", p);
504 }
505 } else if (ch == 'r') { // jint (release mode)
506 jint releaseMode = va_arg(ap, jint);
507 if (releaseMode == 0) {
508 msg += "0";
509 } else if (releaseMode == JNI_ABORT) {
510 msg += "JNI_ABORT";
511 } else if (releaseMode == JNI_COMMIT) {
512 msg += "JNI_COMMIT";
513 } else {
514 StringAppendF(&msg, "invalid release mode %d", releaseMode);
515 }
Elliott Hughes78090d12011-10-07 14:31:47 -0700516 } else if (ch == 'u') { // const char* (Modified UTF-8)
Elliott Hughesa2501992011-08-26 19:39:54 -0700517 const char* utf = va_arg(ap, const char*);
518 if (utf == NULL) {
519 msg += "NULL";
520 } else {
521 StringAppendF(&msg, "\"%s\"", utf);
522 }
523 } else if (ch == '.') {
524 msg += "...";
525 } else {
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700526 JniAbortF(function_name_, "unknown trace format specifier: %c", ch);
Elliott Hughesa2501992011-08-26 19:39:54 -0700527 return;
528 }
529 if (*fmt) {
530 StringAppendF(&msg, ", ");
531 }
532 }
533 va_end(ap);
534
Elliott Hughes485cac42011-12-09 17:49:35 -0800535 if ((flags_ & kFlag_ForceTrace) != 0) {
536 LOG(INFO) << "JNI: call to " << function_name_ << "(" << msg << ")";
537 } else if (entry) {
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700538 if (has_method_) {
Elliott Hughesa0957642011-09-02 14:27:33 -0700539 std::string methodName(PrettyMethod(traceMethod, false));
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700540 LOG(INFO) << "JNI: " << methodName << " -> " << function_name_ << "(" << msg << ")";
541 indent_ = methodName.size() + 1;
Elliott Hughesa2501992011-08-26 19:39:54 -0700542 } else {
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700543 LOG(INFO) << "JNI: -> " << function_name_ << "(" << msg << ")";
544 indent_ = 0;
Elliott Hughesa2501992011-08-26 19:39:54 -0700545 }
546 } else {
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700547 LOG(INFO) << StringPrintf("JNI: %*s<- %s returned %s", indent_, "", function_name_, msg.c_str());
Elliott Hughesa2501992011-08-26 19:39:54 -0700548 }
549 }
550
551 // We always do the thorough checks on entry, and never on exit...
552 if (entry) {
553 va_start(ap, fmt0);
554 for (const char* fmt = fmt0; *fmt; ++fmt) {
555 char ch = *fmt;
556 if (ch == 'a') {
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700557 CheckArray(va_arg(ap, jarray));
Elliott Hughesa2501992011-08-26 19:39:54 -0700558 } else if (ch == 'c') {
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700559 CheckInstance(kClass, va_arg(ap, jclass));
Elliott Hughesa2501992011-08-26 19:39:54 -0700560 } else if (ch == 'L') {
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700561 CheckObject(va_arg(ap, jobject));
Elliott Hughesa2501992011-08-26 19:39:54 -0700562 } else if (ch == 'r') {
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700563 CheckReleaseMode(va_arg(ap, jint));
Elliott Hughesa2501992011-08-26 19:39:54 -0700564 } else if (ch == 's') {
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700565 CheckInstance(kString, va_arg(ap, jstring));
Elliott Hughesa2501992011-08-26 19:39:54 -0700566 } else if (ch == 'u') {
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700567 if ((flags_ & kFlag_Release) != 0) {
568 CheckNonNull(va_arg(ap, const char*));
Elliott Hughesa2501992011-08-26 19:39:54 -0700569 } else {
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700570 bool nullable = ((flags_ & kFlag_NullableUtf) != 0);
571 CheckUtfString(va_arg(ap, const char*), nullable);
Elliott Hughesa2501992011-08-26 19:39:54 -0700572 }
573 } else if (ch == 'z') {
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700574 CheckLengthPositive(va_arg(ap, jsize));
Elliott Hughesa2501992011-08-26 19:39:54 -0700575 } else if (strchr("BCISZbfmpEv", ch) != NULL) {
Elliott Hughesba8eee12012-01-24 20:25:24 -0800576 va_arg(ap, uint32_t); // Skip this argument.
Elliott Hughesa2501992011-08-26 19:39:54 -0700577 } else if (ch == 'D' || ch == 'F') {
578 va_arg(ap, double); // Skip this argument.
579 } else if (ch == 'J') {
Elliott Hughesba8eee12012-01-24 20:25:24 -0800580 va_arg(ap, uint64_t); // Skip this argument.
Elliott Hughesa2501992011-08-26 19:39:54 -0700581 } else if (ch == '.') {
582 } else {
Elliott Hughes3d30d9b2011-12-07 17:35:48 -0800583 LOG(FATAL) << "Unknown check format specifier: " << ch;
Elliott Hughesa2501992011-08-26 19:39:54 -0700584 }
585 }
586 va_end(ap);
587 }
588 }
589
Elliott Hughesa92853e2012-02-07 16:09:27 -0800590 enum InstanceKind {
591 kClass,
Elliott Hughes0f3c5532012-03-30 14:51:51 -0700592 kDirectByteBuffer,
593 kObject,
594 kString,
595 kThrowable,
Elliott Hughesa92853e2012-02-07 16:09:27 -0800596 };
597
598 /*
599 * Verify that "jobj" is a valid non-NULL object reference, and points to
600 * an instance of expectedClass.
601 *
602 * Because we're looking at an object on the GC heap, we have to switch
603 * to "running" mode before doing the checks.
604 */
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700605 bool CheckInstance(InstanceKind kind, jobject java_object)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700606 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Elliott Hughesa92853e2012-02-07 16:09:27 -0800607 const char* what = NULL;
608 switch (kind) {
609 case kClass:
610 what = "jclass";
611 break;
612 case kDirectByteBuffer:
613 what = "direct ByteBuffer";
614 break;
615 case kObject:
616 what = "jobject";
617 break;
618 case kString:
619 what = "jstring";
620 break;
621 case kThrowable:
622 what = "jthrowable";
623 break;
624 default:
Elliott Hughes7b9d9962012-04-20 18:48:18 -0700625 LOG(FATAL) << "Unknown kind " << static_cast<int>(kind);
Elliott Hughesa92853e2012-02-07 16:09:27 -0800626 }
627
628 if (java_object == NULL) {
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700629 JniAbortF(function_name_, "%s received null %s", function_name_, what);
Elliott Hughesa92853e2012-02-07 16:09:27 -0800630 return false;
631 }
632
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800633 mirror::Object* obj = soa_.Decode<mirror::Object*>(java_object);
Elliott Hughesb3bd5f02012-03-08 21:05:27 -0800634 if (!Runtime::Current()->GetHeap()->IsHeapAddress(obj)) {
Mathieu Chartier128c52c2012-10-16 14:12:41 -0700635 Runtime::Current()->GetHeap()->DumpSpaces();
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700636 JniAbortF(function_name_, "%s is an invalid %s: %p (%p)",
637 what, ToStr<IndirectRefKind>(GetIndirectRefKind(java_object)).c_str(), java_object, obj);
Elliott Hughesa92853e2012-02-07 16:09:27 -0800638 return false;
639 }
640
641 bool okay = true;
642 switch (kind) {
643 case kClass:
644 okay = obj->IsClass();
645 break;
646 case kDirectByteBuffer:
647 UNIMPLEMENTED(FATAL);
648 break;
649 case kString:
650 okay = obj->GetClass()->IsStringClass();
651 break;
652 case kThrowable:
653 okay = obj->GetClass()->IsThrowableClass();
654 break;
655 case kObject:
656 break;
657 }
658 if (!okay) {
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700659 JniAbortF(function_name_, "%s has wrong type: %s", what, PrettyTypeOf(obj).c_str());
Elliott Hughesa92853e2012-02-07 16:09:27 -0800660 return false;
661 }
662
663 return true;
664 }
665
Elliott Hughesba8eee12012-01-24 20:25:24 -0800666 private:
Elliott Hughes81ff3182012-03-23 20:35:56 -0700667 // Set "has_method" to true if we have a valid thread with a method pointer.
668 // We won't have one before attaching a thread, after detaching a thread, or
669 // when shutting down the runtime.
Ian Rogers365c1022012-06-22 15:05:28 -0700670 void Init(int flags, const char* functionName, bool has_method) {
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700671 flags_ = flags;
672 function_name_ = functionName;
Elliott Hughes81ff3182012-03-23 20:35:56 -0700673 has_method_ = has_method;
Elliott Hughesa2501992011-08-26 19:39:54 -0700674 }
675
676 /*
677 * Verify that "array" is non-NULL and points to an Array object.
678 *
679 * Since we're dealing with objects, switch to "running" mode.
680 */
Ian Rogersb726dcb2012-09-05 08:57:23 -0700681 void CheckArray(jarray java_array) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Elliott Hughesa2501992011-08-26 19:39:54 -0700682 if (java_array == NULL) {
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700683 JniAbortF(function_name_, "jarray was NULL");
Elliott Hughesa2501992011-08-26 19:39:54 -0700684 return;
685 }
686
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800687 mirror::Array* a = soa_.Decode<mirror::Array*>(java_array);
Elliott Hughesb3bd5f02012-03-08 21:05:27 -0800688 if (!Runtime::Current()->GetHeap()->IsHeapAddress(a)) {
Mathieu Chartier128c52c2012-10-16 14:12:41 -0700689 Runtime::Current()->GetHeap()->DumpSpaces();
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700690 JniAbortF(function_name_, "jarray is an invalid %s: %p (%p)",
691 ToStr<IndirectRefKind>(GetIndirectRefKind(java_array)).c_str(), java_array, a);
Elliott Hughesa2501992011-08-26 19:39:54 -0700692 } else if (!a->IsArrayInstance()) {
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700693 JniAbortF(function_name_, "jarray argument has non-array type: %s", PrettyTypeOf(a).c_str());
Elliott Hughesa2501992011-08-26 19:39:54 -0700694 }
695 }
696
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700697 void CheckLengthPositive(jsize length) {
Elliott Hughesa2501992011-08-26 19:39:54 -0700698 if (length < 0) {
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700699 JniAbortF(function_name_, "negative jsize: %d", length);
Elliott Hughesa2501992011-08-26 19:39:54 -0700700 }
701 }
702
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800703 mirror::Field* CheckFieldID(jfieldID fid) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700704 if (fid == NULL) {
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700705 JniAbortF(function_name_, "jfieldID was NULL");
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700706 return NULL;
707 }
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800708 mirror::Field* f = soa_.DecodeField(fid);
Ian Rogers365c1022012-06-22 15:05:28 -0700709 if (!Runtime::Current()->GetHeap()->IsHeapAddress(f) || !f->IsField()) {
Mathieu Chartier128c52c2012-10-16 14:12:41 -0700710 Runtime::Current()->GetHeap()->DumpSpaces();
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700711 JniAbortF(function_name_, "invalid jfieldID: %p", fid);
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700712 return NULL;
713 }
714 return f;
715 }
716
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800717 mirror::AbstractMethod* CheckMethodID(jmethodID mid) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700718 if (mid == NULL) {
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700719 JniAbortF(function_name_, "jmethodID was NULL");
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700720 return NULL;
721 }
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800722 mirror::AbstractMethod* m = soa_.DecodeMethod(mid);
Ian Rogers365c1022012-06-22 15:05:28 -0700723 if (!Runtime::Current()->GetHeap()->IsHeapAddress(m) || !m->IsMethod()) {
Mathieu Chartier128c52c2012-10-16 14:12:41 -0700724 Runtime::Current()->GetHeap()->DumpSpaces();
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700725 JniAbortF(function_name_, "invalid jmethodID: %p", mid);
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700726 return NULL;
727 }
728 return m;
729 }
730
Elliott Hughesa2501992011-08-26 19:39:54 -0700731 /*
732 * Verify that "jobj" is a valid object, and that it's an object that JNI
733 * is allowed to know about. We allow NULL references.
734 *
735 * Switches to "running" mode before performing checks.
736 */
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700737 void CheckObject(jobject java_object)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700738 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Elliott Hughesa2501992011-08-26 19:39:54 -0700739 if (java_object == NULL) {
740 return;
741 }
742
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800743 mirror::Object* o = soa_.Decode<mirror::Object*>(java_object);
Elliott Hughes88c5c352012-03-15 18:49:48 -0700744 if (!Runtime::Current()->GetHeap()->IsHeapAddress(o)) {
Mathieu Chartier128c52c2012-10-16 14:12:41 -0700745 Runtime::Current()->GetHeap()->DumpSpaces();
Elliott Hughesc5bfa8f2011-08-30 14:32:49 -0700746 // TODO: when we remove work_around_app_jni_bugs, this should be impossible.
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700747 JniAbortF(function_name_, "native code passing in reference to invalid %s: %p",
748 ToStr<IndirectRefKind>(GetIndirectRefKind(java_object)).c_str(), java_object);
Elliott Hughesa2501992011-08-26 19:39:54 -0700749 }
750 }
751
752 /*
753 * Verify that the "mode" argument passed to a primitive array Release
754 * function is one of the valid values.
755 */
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700756 void CheckReleaseMode(jint mode) {
Elliott Hughesa2501992011-08-26 19:39:54 -0700757 if (mode != 0 && mode != JNI_COMMIT && mode != JNI_ABORT) {
Elliott Hughes96a98872012-12-19 14:21:15 -0800758 JniAbortF(function_name_, "unknown value for release mode: %d", mode);
Elliott Hughesa2501992011-08-26 19:39:54 -0700759 }
760 }
761
Ian Rogersb726dcb2012-09-05 08:57:23 -0700762 void CheckThread(int flags) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Elliott Hughesa2501992011-08-26 19:39:54 -0700763 Thread* self = Thread::Current();
764 if (self == NULL) {
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700765 JniAbortF(function_name_, "a thread (tid %d) is making JNI calls without being attached", GetTid());
Elliott Hughesa2501992011-08-26 19:39:54 -0700766 return;
767 }
768
769 // Get the *correct* JNIEnv by going through our TLS pointer.
770 JNIEnvExt* threadEnv = self->GetJniEnv();
771
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700772 // Verify that the current thread is (a) attached and (b) associated with
773 // this particular instance of JNIEnv.
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700774 if (soa_.Env() != threadEnv) {
775 if (soa_.Vm()->work_around_app_jni_bugs) {
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700776 // If we're keeping broken code limping along, we need to suppress the abort...
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700777 LOG(ERROR) << "APP BUG DETECTED: thread " << *self << " using JNIEnv* from thread " << *soa_.Self();
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700778 } else {
779 JniAbortF(function_name_, "thread %s using JNIEnv* from thread %s",
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700780 ToStr<Thread>(*self).c_str(), ToStr<Thread>(*soa_.Self()).c_str());
Elliott Hughesa2501992011-08-26 19:39:54 -0700781 return;
782 }
783 }
784
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700785 // Verify that, if this thread previously made a critical "get" call, we
786 // do the corresponding "release" call before we try anything else.
Elliott Hughesa2501992011-08-26 19:39:54 -0700787 switch (flags & kFlag_CritMask) {
788 case kFlag_CritOkay: // okay to call this method
789 break;
790 case kFlag_CritBad: // not okay to call
791 if (threadEnv->critical) {
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700792 JniAbortF(function_name_, "thread %s using JNI after critical get", ToStr<Thread>(*self).c_str());
Elliott Hughesa2501992011-08-26 19:39:54 -0700793 return;
794 }
795 break;
796 case kFlag_CritGet: // this is a "get" call
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700797 // Don't check here; we allow nested gets.
Elliott Hughesa2501992011-08-26 19:39:54 -0700798 threadEnv->critical++;
799 break;
800 case kFlag_CritRelease: // this is a "release" call
801 threadEnv->critical--;
802 if (threadEnv->critical < 0) {
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700803 JniAbortF(function_name_, "thread %s called too many critical releases", ToStr<Thread>(*self).c_str());
Elliott Hughesa2501992011-08-26 19:39:54 -0700804 return;
805 }
806 break;
807 default:
Elliott Hughes3d30d9b2011-12-07 17:35:48 -0800808 LOG(FATAL) << "Bad flags (internal error): " << flags;
Elliott Hughesa2501992011-08-26 19:39:54 -0700809 }
810
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700811 // Verify that, if an exception has been raised, the native code doesn't
812 // make any JNI calls other than the Exception* methods.
Elliott Hughesa2501992011-08-26 19:39:54 -0700813 if ((flags & kFlag_ExcepOkay) == 0 && self->IsExceptionPending()) {
Ian Rogers62d6c772013-02-27 08:32:07 -0800814 ThrowLocation throw_location;
815 mirror::Throwable* exception = self->GetException(&throw_location);
816 std::string type(PrettyTypeOf(exception));
Elliott Hughes30646832011-10-13 16:59:46 -0700817 // TODO: write native code that doesn't require allocation for dumping an exception.
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700818 // TODO: do we care any more? art always dumps pending exceptions on aborting threads.
Ian Rogers62d6c772013-02-27 08:32:07 -0800819 bool with_stack_trace = (type != "java.lang.OutOfMemoryError");
820 if (with_stack_trace) {
821 JniAbortF(function_name_, "JNI %s called with pending exception '%s' thrown in %s\n%s",
822 function_name_, type.c_str(), throw_location.Dump().c_str(),
823 jniGetStackTrace(soa_.Env()).c_str());
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700824 } else {
Ian Rogers62d6c772013-02-27 08:32:07 -0800825 JniAbortF(function_name_, "JNI %s called with pending exception '%s' thrown in %s",
826 function_name_, type.c_str(), throw_location.Dump().c_str());
Elliott Hughes30646832011-10-13 16:59:46 -0700827 }
Elliott Hughesa2501992011-08-26 19:39:54 -0700828 return;
829 }
830 }
831
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700832 // Verifies that "bytes" points to valid Modified UTF-8 data.
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700833 void CheckUtfString(const char* bytes, bool nullable) {
Elliott Hughesa2501992011-08-26 19:39:54 -0700834 if (bytes == NULL) {
835 if (!nullable) {
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700836 JniAbortF(function_name_, "non-nullable const char* was NULL");
Elliott Hughesa2501992011-08-26 19:39:54 -0700837 return;
838 }
839 return;
840 }
841
842 const char* errorKind = NULL;
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700843 uint8_t utf8 = CheckUtfBytes(bytes, &errorKind);
Elliott Hughesa2501992011-08-26 19:39:54 -0700844 if (errorKind != NULL) {
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700845 JniAbortF(function_name_,
846 "input is not valid Modified UTF-8: illegal %s byte %#x\n"
847 " string: '%s'", errorKind, utf8, bytes);
Elliott Hughesa2501992011-08-26 19:39:54 -0700848 return;
849 }
850 }
851
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700852 static uint8_t CheckUtfBytes(const char* bytes, const char** errorKind) {
Elliott Hughesa2501992011-08-26 19:39:54 -0700853 while (*bytes != '\0') {
854 uint8_t utf8 = *(bytes++);
855 // Switch on the high four bits.
856 switch (utf8 >> 4) {
857 case 0x00:
858 case 0x01:
859 case 0x02:
860 case 0x03:
861 case 0x04:
862 case 0x05:
863 case 0x06:
864 case 0x07:
865 // Bit pattern 0xxx. No need for any extra bytes.
866 break;
867 case 0x08:
868 case 0x09:
869 case 0x0a:
870 case 0x0b:
871 case 0x0f:
872 /*
873 * Bit pattern 10xx or 1111, which are illegal start bytes.
874 * Note: 1111 is valid for normal UTF-8, but not the
Elliott Hughes78090d12011-10-07 14:31:47 -0700875 * Modified UTF-8 used here.
Elliott Hughesa2501992011-08-26 19:39:54 -0700876 */
877 *errorKind = "start";
878 return utf8;
879 case 0x0e:
880 // Bit pattern 1110, so there are two additional bytes.
881 utf8 = *(bytes++);
882 if ((utf8 & 0xc0) != 0x80) {
883 *errorKind = "continuation";
884 return utf8;
885 }
886 // Fall through to take care of the final byte.
887 case 0x0c:
888 case 0x0d:
889 // Bit pattern 110x, so there is one additional byte.
890 utf8 = *(bytes++);
891 if ((utf8 & 0xc0) != 0x80) {
892 *errorKind = "continuation";
893 return utf8;
894 }
895 break;
896 }
897 }
898 return 0;
899 }
900
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700901 const ScopedObjectAccess soa_;
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700902 const char* function_name_;
903 int flags_;
904 bool has_method_;
Elliott Hughes92cb4982011-12-16 16:57:28 -0800905 int indent_;
Elliott Hughesa2501992011-08-26 19:39:54 -0700906
907 DISALLOW_COPY_AND_ASSIGN(ScopedCheck);
908};
909
910#define CHECK_JNI_ENTRY(flags, types, args...) \
911 ScopedCheck sc(env, flags, __FUNCTION__); \
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700912 sc.Check(true, types, ##args)
Elliott Hughesa2501992011-08-26 19:39:54 -0700913
914#define CHECK_JNI_EXIT(type, exp) ({ \
Elliott Hughes362f9bc2011-10-17 18:56:41 -0700915 typeof(exp) _rc = (exp); \
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700916 sc.Check(false, type, _rc); \
Elliott Hughesa2501992011-08-26 19:39:54 -0700917 _rc; })
918#define CHECK_JNI_EXIT_VOID() \
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700919 sc.Check(false, "V")
Elliott Hughesa2501992011-08-26 19:39:54 -0700920
921/*
922 * ===========================================================================
923 * Guarded arrays
924 * ===========================================================================
925 */
926
927#define kGuardLen 512 /* must be multiple of 2 */
928#define kGuardPattern 0xd5e3 /* uncommon values; d5e3d5e3 invalid addr */
929#define kGuardMagic 0xffd5aa96
930
931/* this gets tucked in at the start of the buffer; struct size must be even */
932struct GuardedCopy {
933 uint32_t magic;
934 uLong adler;
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700935 size_t original_length;
936 const void* original_ptr;
Elliott Hughesa2501992011-08-26 19:39:54 -0700937
938 /* find the GuardedCopy given the pointer into the "live" data */
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700939 static inline const GuardedCopy* FromData(const void* dataBuf) {
940 return reinterpret_cast<const GuardedCopy*>(ActualBuffer(dataBuf));
Elliott Hughesa2501992011-08-26 19:39:54 -0700941 }
942
943 /*
944 * Create an over-sized buffer to hold the contents of "buf". Copy it in,
945 * filling in the area around it with guard data.
946 *
947 * We use a 16-bit pattern to make a rogue memset less likely to elude us.
948 */
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700949 static void* Create(const void* buf, size_t len, bool modOkay) {
950 size_t newLen = ActualLength(len);
951 uint8_t* newBuf = DebugAlloc(newLen);
Elliott Hughesa2501992011-08-26 19:39:54 -0700952
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700953 // Fill it in with a pattern.
Elliott Hughesba8eee12012-01-24 20:25:24 -0800954 uint16_t* pat = reinterpret_cast<uint16_t*>(newBuf);
Elliott Hughesa2501992011-08-26 19:39:54 -0700955 for (size_t i = 0; i < newLen / 2; i++) {
956 *pat++ = kGuardPattern;
957 }
958
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700959 // Copy the data in; note "len" could be zero.
Elliott Hughesa2501992011-08-26 19:39:54 -0700960 memcpy(newBuf + kGuardLen / 2, buf, len);
961
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700962 // If modification is not expected, grab a checksum.
Elliott Hughesa2501992011-08-26 19:39:54 -0700963 uLong adler = 0;
964 if (!modOkay) {
965 adler = adler32(0L, Z_NULL, 0);
Elliott Hughesba8eee12012-01-24 20:25:24 -0800966 adler = adler32(adler, reinterpret_cast<const Bytef*>(buf), len);
967 *reinterpret_cast<uLong*>(newBuf) = adler;
Elliott Hughesa2501992011-08-26 19:39:54 -0700968 }
969
970 GuardedCopy* pExtra = reinterpret_cast<GuardedCopy*>(newBuf);
971 pExtra->magic = kGuardMagic;
972 pExtra->adler = adler;
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700973 pExtra->original_ptr = buf;
974 pExtra->original_length = len;
Elliott Hughesa2501992011-08-26 19:39:54 -0700975
976 return newBuf + kGuardLen / 2;
977 }
978
979 /*
980 * Free up the guard buffer, scrub it, and return the original pointer.
981 */
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700982 static void* Destroy(void* dataBuf) {
983 const GuardedCopy* pExtra = GuardedCopy::FromData(dataBuf);
Elliott Hughesba8eee12012-01-24 20:25:24 -0800984 void* original_ptr = const_cast<void*>(pExtra->original_ptr);
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700985 size_t len = pExtra->original_length;
986 DebugFree(dataBuf, len);
987 return original_ptr;
Elliott Hughesa2501992011-08-26 19:39:54 -0700988 }
989
990 /*
991 * Verify the guard area and, if "modOkay" is false, that the data itself
992 * has not been altered.
993 *
994 * The caller has already checked that "dataBuf" is non-NULL.
995 */
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700996 static void Check(const char* functionName, const void* dataBuf, bool modOkay) {
Elliott Hughesa2501992011-08-26 19:39:54 -0700997 static const uint32_t kMagicCmp = kGuardMagic;
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700998 const uint8_t* fullBuf = ActualBuffer(dataBuf);
999 const GuardedCopy* pExtra = GuardedCopy::FromData(dataBuf);
Elliott Hughesa2501992011-08-26 19:39:54 -07001000
Elliott Hughes3f6635a2012-06-19 13:37:49 -07001001 // Before we do anything with "pExtra", check the magic number. We
1002 // do the check with memcmp rather than "==" in case the pointer is
1003 // unaligned. If it points to completely bogus memory we're going
1004 // to crash, but there's no easy way around that.
Elliott Hughesa2501992011-08-26 19:39:54 -07001005 if (memcmp(&pExtra->magic, &kMagicCmp, 4) != 0) {
1006 uint8_t buf[4];
1007 memcpy(buf, &pExtra->magic, 4);
Elliott Hughes3f6635a2012-06-19 13:37:49 -07001008 JniAbortF(functionName,
1009 "guard magic does not match (found 0x%02x%02x%02x%02x) -- incorrect data pointer %p?",
1010 buf[3], buf[2], buf[1], buf[0], dataBuf); // Assumes little-endian.
Elliott Hughesa2501992011-08-26 19:39:54 -07001011 }
1012
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001013 size_t len = pExtra->original_length;
Elliott Hughesa2501992011-08-26 19:39:54 -07001014
Elliott Hughes3f6635a2012-06-19 13:37:49 -07001015 // Check bottom half of guard; skip over optional checksum storage.
Elliott Hughesba8eee12012-01-24 20:25:24 -08001016 const uint16_t* pat = reinterpret_cast<const uint16_t*>(fullBuf);
Elliott Hughesa2501992011-08-26 19:39:54 -07001017 for (size_t i = sizeof(GuardedCopy) / 2; i < (kGuardLen / 2 - sizeof(GuardedCopy)) / 2; i++) {
1018 if (pat[i] != kGuardPattern) {
Elliott Hughes3f6635a2012-06-19 13:37:49 -07001019 JniAbortF(functionName, "guard pattern(1) disturbed at %p +%d", fullBuf, i*2);
Elliott Hughesa2501992011-08-26 19:39:54 -07001020 }
1021 }
1022
1023 int offset = kGuardLen / 2 + len;
1024 if (offset & 0x01) {
Elliott Hughes3f6635a2012-06-19 13:37:49 -07001025 // Odd byte; expected value depends on endian.
Elliott Hughesa2501992011-08-26 19:39:54 -07001026 const uint16_t patSample = kGuardPattern;
Elliott Hughes3f6635a2012-06-19 13:37:49 -07001027 uint8_t expected_byte = reinterpret_cast<const uint8_t*>(&patSample)[1];
1028 if (fullBuf[offset] != expected_byte) {
1029 JniAbortF(functionName, "guard pattern disturbed in odd byte after %p +%d 0x%02x 0x%02x",
1030 fullBuf, offset, fullBuf[offset], expected_byte);
Elliott Hughesa2501992011-08-26 19:39:54 -07001031 }
1032 offset++;
1033 }
1034
Elliott Hughes3f6635a2012-06-19 13:37:49 -07001035 // Check top half of guard.
Elliott Hughesba8eee12012-01-24 20:25:24 -08001036 pat = reinterpret_cast<const uint16_t*>(fullBuf + offset);
Elliott Hughesa2501992011-08-26 19:39:54 -07001037 for (size_t i = 0; i < kGuardLen / 4; i++) {
1038 if (pat[i] != kGuardPattern) {
Elliott Hughes3f6635a2012-06-19 13:37:49 -07001039 JniAbortF(functionName, "guard pattern(2) disturbed at %p +%d", fullBuf, offset + i*2);
Elliott Hughesa2501992011-08-26 19:39:54 -07001040 }
1041 }
1042
Elliott Hughes3f6635a2012-06-19 13:37:49 -07001043 // If modification is not expected, verify checksum. Strictly speaking
1044 // this is wrong: if we told the client that we made a copy, there's no
1045 // reason they can't alter the buffer.
Elliott Hughesa2501992011-08-26 19:39:54 -07001046 if (!modOkay) {
1047 uLong adler = adler32(0L, Z_NULL, 0);
1048 adler = adler32(adler, (const Bytef*)dataBuf, len);
1049 if (pExtra->adler != adler) {
Elliott Hughes3f6635a2012-06-19 13:37:49 -07001050 JniAbortF(functionName, "buffer modified (0x%08lx vs 0x%08lx) at address %p",
1051 pExtra->adler, adler, dataBuf);
Elliott Hughesa2501992011-08-26 19:39:54 -07001052 }
1053 }
1054 }
1055
1056 private:
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001057 static uint8_t* DebugAlloc(size_t len) {
Elliott Hughesa2501992011-08-26 19:39:54 -07001058 void* result = mmap(NULL, len, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON, -1, 0);
1059 if (result == MAP_FAILED) {
1060 PLOG(FATAL) << "GuardedCopy::create mmap(" << len << ") failed";
1061 }
1062 return reinterpret_cast<uint8_t*>(result);
1063 }
1064
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001065 static void DebugFree(void* dataBuf, size_t len) {
1066 uint8_t* fullBuf = ActualBuffer(dataBuf);
1067 size_t totalByteCount = ActualLength(len);
Elliott Hughesa2501992011-08-26 19:39:54 -07001068 // TODO: we could mprotect instead, and keep the allocation around for a while.
1069 // This would be even more expensive, but it might catch more errors.
1070 // if (mprotect(fullBuf, totalByteCount, PROT_NONE) != 0) {
Elliott Hughes7b9d9962012-04-20 18:48:18 -07001071 // PLOG(WARNING) << "mprotect(PROT_NONE) failed";
Elliott Hughesa2501992011-08-26 19:39:54 -07001072 // }
1073 if (munmap(fullBuf, totalByteCount) != 0) {
Elliott Hughesba8eee12012-01-24 20:25:24 -08001074 PLOG(FATAL) << "munmap(" << reinterpret_cast<void*>(fullBuf) << ", " << totalByteCount << ") failed";
Elliott Hughesa2501992011-08-26 19:39:54 -07001075 }
1076 }
1077
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001078 static const uint8_t* ActualBuffer(const void* dataBuf) {
Elliott Hughesa2501992011-08-26 19:39:54 -07001079 return reinterpret_cast<const uint8_t*>(dataBuf) - kGuardLen / 2;
1080 }
1081
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001082 static uint8_t* ActualBuffer(void* dataBuf) {
Elliott Hughesa2501992011-08-26 19:39:54 -07001083 return reinterpret_cast<uint8_t*>(dataBuf) - kGuardLen / 2;
1084 }
1085
1086 // Underlying length of a user allocation of 'length' bytes.
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001087 static size_t ActualLength(size_t length) {
Elliott Hughesa2501992011-08-26 19:39:54 -07001088 return (length + kGuardLen + 1) & ~0x01;
1089 }
1090};
1091
1092/*
1093 * Create a guarded copy of a primitive array. Modifications to the copied
1094 * data are allowed. Returns a pointer to the copied data.
1095 */
Elliott Hughes3f6635a2012-06-19 13:37:49 -07001096static void* CreateGuardedPACopy(JNIEnv* env, const jarray java_array, jboolean* isCopy) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -07001097 ScopedObjectAccess soa(env);
Elliott Hughesa2501992011-08-26 19:39:54 -07001098
Ian Rogers2dd0e2c2013-01-24 12:42:14 -08001099 mirror::Array* a = soa.Decode<mirror::Array*>(java_array);
Ian Rogersa15e67d2012-02-28 13:51:55 -08001100 size_t component_size = a->GetClass()->GetComponentSize();
1101 size_t byte_count = a->GetLength() * component_size;
1102 void* result = GuardedCopy::Create(a->GetRawData(component_size), byte_count, true);
Elliott Hughesa2501992011-08-26 19:39:54 -07001103 if (isCopy != NULL) {
1104 *isCopy = JNI_TRUE;
1105 }
1106 return result;
1107}
1108
1109/*
1110 * Perform the array "release" operation, which may or may not copy data
Elliott Hughes81ff3182012-03-23 20:35:56 -07001111 * back into the managed heap, and may or may not release the underlying storage.
Elliott Hughesa2501992011-08-26 19:39:54 -07001112 */
Elliott Hughes3f6635a2012-06-19 13:37:49 -07001113static void ReleaseGuardedPACopy(JNIEnv* env, jarray java_array, void* dataBuf, int mode) {
Elliott Hughesa2501992011-08-26 19:39:54 -07001114 if (reinterpret_cast<uintptr_t>(dataBuf) == kNoCopyMagic) {
1115 return;
1116 }
1117
Ian Rogers00f7d0e2012-07-19 15:28:27 -07001118 ScopedObjectAccess soa(env);
Ian Rogers2dd0e2c2013-01-24 12:42:14 -08001119 mirror::Array* a = soa.Decode<mirror::Array*>(java_array);
Elliott Hughesa2501992011-08-26 19:39:54 -07001120
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001121 GuardedCopy::Check(__FUNCTION__, dataBuf, true);
Elliott Hughesa2501992011-08-26 19:39:54 -07001122
1123 if (mode != JNI_ABORT) {
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001124 size_t len = GuardedCopy::FromData(dataBuf)->original_length;
Ian Rogersa15e67d2012-02-28 13:51:55 -08001125 memcpy(a->GetRawData(a->GetClass()->GetComponentSize()), dataBuf, len);
Elliott Hughesa2501992011-08-26 19:39:54 -07001126 }
1127 if (mode != JNI_COMMIT) {
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001128 GuardedCopy::Destroy(dataBuf);
Elliott Hughesa2501992011-08-26 19:39:54 -07001129 }
1130}
1131
1132/*
1133 * ===========================================================================
1134 * JNI functions
1135 * ===========================================================================
1136 */
1137
1138class CheckJNI {
1139 public:
1140 static jint GetVersion(JNIEnv* env) {
1141 CHECK_JNI_ENTRY(kFlag_Default, "E", env);
1142 return CHECK_JNI_EXIT("I", baseEnv(env)->GetVersion(env));
1143 }
1144
1145 static jclass DefineClass(JNIEnv* env, const char* name, jobject loader, const jbyte* buf, jsize bufLen) {
1146 CHECK_JNI_ENTRY(kFlag_Default, "EuLpz", env, name, loader, buf, bufLen);
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001147 sc.CheckClassName(name);
Elliott Hughesa2501992011-08-26 19:39:54 -07001148 return CHECK_JNI_EXIT("c", baseEnv(env)->DefineClass(env, name, loader, buf, bufLen));
1149 }
1150
1151 static jclass FindClass(JNIEnv* env, const char* name) {
1152 CHECK_JNI_ENTRY(kFlag_Default, "Eu", env, name);
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001153 sc.CheckClassName(name);
Elliott Hughesa2501992011-08-26 19:39:54 -07001154 return CHECK_JNI_EXIT("c", baseEnv(env)->FindClass(env, name));
1155 }
1156
Elliott Hughese84278b2012-03-22 10:06:53 -07001157 static jclass GetSuperclass(JNIEnv* env, jclass c) {
1158 CHECK_JNI_ENTRY(kFlag_Default, "Ec", env, c);
1159 return CHECK_JNI_EXIT("c", baseEnv(env)->GetSuperclass(env, c));
Elliott Hughesa2501992011-08-26 19:39:54 -07001160 }
1161
Elliott Hughese84278b2012-03-22 10:06:53 -07001162 static jboolean IsAssignableFrom(JNIEnv* env, jclass c1, jclass c2) {
1163 CHECK_JNI_ENTRY(kFlag_Default, "Ecc", env, c1, c2);
1164 return CHECK_JNI_EXIT("b", baseEnv(env)->IsAssignableFrom(env, c1, c2));
Elliott Hughesa2501992011-08-26 19:39:54 -07001165 }
1166
1167 static jmethodID FromReflectedMethod(JNIEnv* env, jobject method) {
1168 CHECK_JNI_ENTRY(kFlag_Default, "EL", env, method);
1169 // TODO: check that 'field' is a java.lang.reflect.Method.
1170 return CHECK_JNI_EXIT("m", baseEnv(env)->FromReflectedMethod(env, method));
1171 }
1172
1173 static jfieldID FromReflectedField(JNIEnv* env, jobject field) {
1174 CHECK_JNI_ENTRY(kFlag_Default, "EL", env, field);
1175 // TODO: check that 'field' is a java.lang.reflect.Field.
1176 return CHECK_JNI_EXIT("f", baseEnv(env)->FromReflectedField(env, field));
1177 }
1178
1179 static jobject ToReflectedMethod(JNIEnv* env, jclass cls, jmethodID mid, jboolean isStatic) {
1180 CHECK_JNI_ENTRY(kFlag_Default, "Ecmb", env, cls, mid, isStatic);
1181 return CHECK_JNI_EXIT("L", baseEnv(env)->ToReflectedMethod(env, cls, mid, isStatic));
1182 }
1183
1184 static jobject ToReflectedField(JNIEnv* env, jclass cls, jfieldID fid, jboolean isStatic) {
1185 CHECK_JNI_ENTRY(kFlag_Default, "Ecfb", env, cls, fid, isStatic);
1186 return CHECK_JNI_EXIT("L", baseEnv(env)->ToReflectedField(env, cls, fid, isStatic));
1187 }
1188
1189 static jint Throw(JNIEnv* env, jthrowable obj) {
1190 CHECK_JNI_ENTRY(kFlag_Default, "EL", env, obj);
1191 // TODO: check that 'obj' is a java.lang.Throwable.
1192 return CHECK_JNI_EXIT("I", baseEnv(env)->Throw(env, obj));
1193 }
1194
Elliott Hughese84278b2012-03-22 10:06:53 -07001195 static jint ThrowNew(JNIEnv* env, jclass c, const char* message) {
1196 CHECK_JNI_ENTRY(kFlag_NullableUtf, "Ecu", env, c, message);
1197 return CHECK_JNI_EXIT("I", baseEnv(env)->ThrowNew(env, c, message));
Elliott Hughesa2501992011-08-26 19:39:54 -07001198 }
1199
1200 static jthrowable ExceptionOccurred(JNIEnv* env) {
1201 CHECK_JNI_ENTRY(kFlag_ExcepOkay, "E", env);
1202 return CHECK_JNI_EXIT("L", baseEnv(env)->ExceptionOccurred(env));
1203 }
1204
1205 static void ExceptionDescribe(JNIEnv* env) {
1206 CHECK_JNI_ENTRY(kFlag_ExcepOkay, "E", env);
1207 baseEnv(env)->ExceptionDescribe(env);
1208 CHECK_JNI_EXIT_VOID();
1209 }
1210
1211 static void ExceptionClear(JNIEnv* env) {
1212 CHECK_JNI_ENTRY(kFlag_ExcepOkay, "E", env);
1213 baseEnv(env)->ExceptionClear(env);
1214 CHECK_JNI_EXIT_VOID();
1215 }
1216
1217 static void FatalError(JNIEnv* env, const char* msg) {
1218 CHECK_JNI_ENTRY(kFlag_NullableUtf, "Eu", env, msg);
1219 baseEnv(env)->FatalError(env, msg);
1220 CHECK_JNI_EXIT_VOID();
1221 }
1222
1223 static jint PushLocalFrame(JNIEnv* env, jint capacity) {
1224 CHECK_JNI_ENTRY(kFlag_Default | kFlag_ExcepOkay, "EI", env, capacity);
1225 return CHECK_JNI_EXIT("I", baseEnv(env)->PushLocalFrame(env, capacity));
1226 }
1227
1228 static jobject PopLocalFrame(JNIEnv* env, jobject res) {
1229 CHECK_JNI_ENTRY(kFlag_Default | kFlag_ExcepOkay, "EL", env, res);
1230 return CHECK_JNI_EXIT("L", baseEnv(env)->PopLocalFrame(env, res));
1231 }
1232
1233 static jobject NewGlobalRef(JNIEnv* env, jobject obj) {
1234 CHECK_JNI_ENTRY(kFlag_Default, "EL", env, obj);
1235 return CHECK_JNI_EXIT("L", baseEnv(env)->NewGlobalRef(env, obj));
1236 }
1237
1238 static jobject NewLocalRef(JNIEnv* env, jobject ref) {
1239 CHECK_JNI_ENTRY(kFlag_Default, "EL", env, ref);
1240 return CHECK_JNI_EXIT("L", baseEnv(env)->NewLocalRef(env, ref));
1241 }
1242
1243 static void DeleteGlobalRef(JNIEnv* env, jobject globalRef) {
1244 CHECK_JNI_ENTRY(kFlag_Default | kFlag_ExcepOkay, "EL", env, globalRef);
1245 if (globalRef != NULL && GetIndirectRefKind(globalRef) != kGlobal) {
Elliott Hughes3f6635a2012-06-19 13:37:49 -07001246 JniAbortF(__FUNCTION__, "DeleteGlobalRef on %s: %p",
1247 ToStr<IndirectRefKind>(GetIndirectRefKind(globalRef)).c_str(), globalRef);
Elliott Hughesa2501992011-08-26 19:39:54 -07001248 } else {
1249 baseEnv(env)->DeleteGlobalRef(env, globalRef);
1250 CHECK_JNI_EXIT_VOID();
1251 }
1252 }
1253
1254 static void DeleteWeakGlobalRef(JNIEnv* env, jweak weakGlobalRef) {
1255 CHECK_JNI_ENTRY(kFlag_Default | kFlag_ExcepOkay, "EL", env, weakGlobalRef);
1256 if (weakGlobalRef != NULL && GetIndirectRefKind(weakGlobalRef) != kWeakGlobal) {
Elliott Hughes3f6635a2012-06-19 13:37:49 -07001257 JniAbortF(__FUNCTION__, "DeleteWeakGlobalRef on %s: %p",
1258 ToStr<IndirectRefKind>(GetIndirectRefKind(weakGlobalRef)).c_str(), weakGlobalRef);
Elliott Hughesa2501992011-08-26 19:39:54 -07001259 } else {
1260 baseEnv(env)->DeleteWeakGlobalRef(env, weakGlobalRef);
1261 CHECK_JNI_EXIT_VOID();
1262 }
1263 }
1264
1265 static void DeleteLocalRef(JNIEnv* env, jobject localRef) {
1266 CHECK_JNI_ENTRY(kFlag_Default | kFlag_ExcepOkay, "EL", env, localRef);
Ian Rogers959f8ed2012-02-07 16:33:37 -08001267 if (localRef != NULL && GetIndirectRefKind(localRef) != kLocal && !IsSirtLocalRef(env, localRef)) {
Elliott Hughes3f6635a2012-06-19 13:37:49 -07001268 JniAbortF(__FUNCTION__, "DeleteLocalRef on %s: %p",
1269 ToStr<IndirectRefKind>(GetIndirectRefKind(localRef)).c_str(), localRef);
Elliott Hughesa2501992011-08-26 19:39:54 -07001270 } else {
1271 baseEnv(env)->DeleteLocalRef(env, localRef);
1272 CHECK_JNI_EXIT_VOID();
1273 }
1274 }
1275
1276 static jint EnsureLocalCapacity(JNIEnv *env, jint capacity) {
1277 CHECK_JNI_ENTRY(kFlag_Default, "EI", env, capacity);
1278 return CHECK_JNI_EXIT("I", baseEnv(env)->EnsureLocalCapacity(env, capacity));
1279 }
1280
1281 static jboolean IsSameObject(JNIEnv* env, jobject ref1, jobject ref2) {
1282 CHECK_JNI_ENTRY(kFlag_Default, "ELL", env, ref1, ref2);
1283 return CHECK_JNI_EXIT("b", baseEnv(env)->IsSameObject(env, ref1, ref2));
1284 }
1285
Elliott Hughese84278b2012-03-22 10:06:53 -07001286 static jobject AllocObject(JNIEnv* env, jclass c) {
1287 CHECK_JNI_ENTRY(kFlag_Default, "Ec", env, c);
1288 return CHECK_JNI_EXIT("L", baseEnv(env)->AllocObject(env, c));
Elliott Hughesa2501992011-08-26 19:39:54 -07001289 }
1290
Elliott Hughese84278b2012-03-22 10:06:53 -07001291 static jobject NewObject(JNIEnv* env, jclass c, jmethodID mid, ...) {
1292 CHECK_JNI_ENTRY(kFlag_Default, "Ecm.", env, c, mid);
Elliott Hughesa2501992011-08-26 19:39:54 -07001293 va_list args;
1294 va_start(args, mid);
Elliott Hughese84278b2012-03-22 10:06:53 -07001295 jobject result = baseEnv(env)->NewObjectV(env, c, mid, args);
Elliott Hughesa2501992011-08-26 19:39:54 -07001296 va_end(args);
1297 return CHECK_JNI_EXIT("L", result);
1298 }
1299
Elliott Hughese84278b2012-03-22 10:06:53 -07001300 static jobject NewObjectV(JNIEnv* env, jclass c, jmethodID mid, va_list args) {
1301 CHECK_JNI_ENTRY(kFlag_Default, "Ecm.", env, c, mid);
1302 return CHECK_JNI_EXIT("L", baseEnv(env)->NewObjectV(env, c, mid, args));
Elliott Hughesa2501992011-08-26 19:39:54 -07001303 }
1304
Elliott Hughese84278b2012-03-22 10:06:53 -07001305 static jobject NewObjectA(JNIEnv* env, jclass c, jmethodID mid, jvalue* args) {
1306 CHECK_JNI_ENTRY(kFlag_Default, "Ecm.", env, c, mid);
1307 return CHECK_JNI_EXIT("L", baseEnv(env)->NewObjectA(env, c, mid, args));
Elliott Hughesa2501992011-08-26 19:39:54 -07001308 }
1309
1310 static jclass GetObjectClass(JNIEnv* env, jobject obj) {
1311 CHECK_JNI_ENTRY(kFlag_Default, "EL", env, obj);
1312 return CHECK_JNI_EXIT("c", baseEnv(env)->GetObjectClass(env, obj));
1313 }
1314
Elliott Hughese84278b2012-03-22 10:06:53 -07001315 static jboolean IsInstanceOf(JNIEnv* env, jobject obj, jclass c) {
1316 CHECK_JNI_ENTRY(kFlag_Default, "ELc", env, obj, c);
1317 return CHECK_JNI_EXIT("b", baseEnv(env)->IsInstanceOf(env, obj, c));
Elliott Hughesa2501992011-08-26 19:39:54 -07001318 }
1319
Elliott Hughese84278b2012-03-22 10:06:53 -07001320 static jmethodID GetMethodID(JNIEnv* env, jclass c, const char* name, const char* sig) {
1321 CHECK_JNI_ENTRY(kFlag_Default, "Ecuu", env, c, name, sig);
1322 return CHECK_JNI_EXIT("m", baseEnv(env)->GetMethodID(env, c, name, sig));
Elliott Hughesa2501992011-08-26 19:39:54 -07001323 }
1324
Elliott Hughese84278b2012-03-22 10:06:53 -07001325 static jfieldID GetFieldID(JNIEnv* env, jclass c, const char* name, const char* sig) {
1326 CHECK_JNI_ENTRY(kFlag_Default, "Ecuu", env, c, name, sig);
1327 return CHECK_JNI_EXIT("f", baseEnv(env)->GetFieldID(env, c, name, sig));
Elliott Hughesa2501992011-08-26 19:39:54 -07001328 }
1329
Elliott Hughese84278b2012-03-22 10:06:53 -07001330 static jmethodID GetStaticMethodID(JNIEnv* env, jclass c, const char* name, const char* sig) {
1331 CHECK_JNI_ENTRY(kFlag_Default, "Ecuu", env, c, name, sig);
1332 return CHECK_JNI_EXIT("m", baseEnv(env)->GetStaticMethodID(env, c, name, sig));
Elliott Hughesa2501992011-08-26 19:39:54 -07001333 }
1334
Elliott Hughese84278b2012-03-22 10:06:53 -07001335 static jfieldID GetStaticFieldID(JNIEnv* env, jclass c, const char* name, const char* sig) {
1336 CHECK_JNI_ENTRY(kFlag_Default, "Ecuu", env, c, name, sig);
1337 return CHECK_JNI_EXIT("f", baseEnv(env)->GetStaticFieldID(env, c, name, sig));
Elliott Hughesa2501992011-08-26 19:39:54 -07001338 }
1339
1340#define FIELD_ACCESSORS(_ctype, _jname, _type) \
Elliott Hughese84278b2012-03-22 10:06:53 -07001341 static _ctype GetStatic##_jname##Field(JNIEnv* env, jclass c, jfieldID fid) { \
1342 CHECK_JNI_ENTRY(kFlag_Default, "Ecf", env, c, fid); \
1343 sc.CheckStaticFieldID(c, fid); \
1344 return CHECK_JNI_EXIT(_type, baseEnv(env)->GetStatic##_jname##Field(env, c, fid)); \
Elliott Hughesa2501992011-08-26 19:39:54 -07001345 } \
1346 static _ctype Get##_jname##Field(JNIEnv* env, jobject obj, jfieldID fid) { \
1347 CHECK_JNI_ENTRY(kFlag_Default, "ELf", env, obj, fid); \
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001348 sc.CheckInstanceFieldID(obj, fid); \
Elliott Hughesa2501992011-08-26 19:39:54 -07001349 return CHECK_JNI_EXIT(_type, baseEnv(env)->Get##_jname##Field(env, obj, fid)); \
1350 } \
Elliott Hughese84278b2012-03-22 10:06:53 -07001351 static void SetStatic##_jname##Field(JNIEnv* env, jclass c, jfieldID fid, _ctype value) { \
1352 CHECK_JNI_ENTRY(kFlag_Default, "Ecf" _type, env, c, fid, value); \
1353 sc.CheckStaticFieldID(c, fid); \
Elliott Hughesa2501992011-08-26 19:39:54 -07001354 /* "value" arg only used when type == ref */ \
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001355 sc.CheckFieldType((jobject)(uint32_t)value, fid, _type[0], true); \
Elliott Hughese84278b2012-03-22 10:06:53 -07001356 baseEnv(env)->SetStatic##_jname##Field(env, c, fid, value); \
Elliott Hughesa2501992011-08-26 19:39:54 -07001357 CHECK_JNI_EXIT_VOID(); \
1358 } \
1359 static void Set##_jname##Field(JNIEnv* env, jobject obj, jfieldID fid, _ctype value) { \
1360 CHECK_JNI_ENTRY(kFlag_Default, "ELf" _type, env, obj, fid, value); \
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001361 sc.CheckInstanceFieldID(obj, fid); \
Elliott Hughesa2501992011-08-26 19:39:54 -07001362 /* "value" arg only used when type == ref */ \
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001363 sc.CheckFieldType((jobject)(uint32_t) value, fid, _type[0], false); \
Elliott Hughesa2501992011-08-26 19:39:54 -07001364 baseEnv(env)->Set##_jname##Field(env, obj, fid, value); \
1365 CHECK_JNI_EXIT_VOID(); \
1366 }
1367
1368FIELD_ACCESSORS(jobject, Object, "L");
1369FIELD_ACCESSORS(jboolean, Boolean, "Z");
1370FIELD_ACCESSORS(jbyte, Byte, "B");
1371FIELD_ACCESSORS(jchar, Char, "C");
1372FIELD_ACCESSORS(jshort, Short, "S");
1373FIELD_ACCESSORS(jint, Int, "I");
1374FIELD_ACCESSORS(jlong, Long, "J");
1375FIELD_ACCESSORS(jfloat, Float, "F");
1376FIELD_ACCESSORS(jdouble, Double, "D");
1377
1378#define CALL(_ctype, _jname, _retdecl, _retasgn, _retok, _retsig) \
1379 /* Virtual... */ \
1380 static _ctype Call##_jname##Method(JNIEnv* env, jobject obj, \
1381 jmethodID mid, ...) \
1382 { \
1383 CHECK_JNI_ENTRY(kFlag_Default, "ELm.", env, obj, mid); /* TODO: args! */ \
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001384 sc.CheckSig(mid, _retsig, false); \
1385 sc.CheckVirtualMethod(obj, mid); \
Elliott Hughesa2501992011-08-26 19:39:54 -07001386 _retdecl; \
1387 va_list args; \
1388 va_start(args, mid); \
Elliott Hughesba8eee12012-01-24 20:25:24 -08001389 _retasgn(baseEnv(env)->Call##_jname##MethodV(env, obj, mid, args)); \
Elliott Hughesa2501992011-08-26 19:39:54 -07001390 va_end(args); \
1391 _retok; \
1392 } \
1393 static _ctype Call##_jname##MethodV(JNIEnv* env, jobject obj, \
1394 jmethodID mid, va_list args) \
1395 { \
1396 CHECK_JNI_ENTRY(kFlag_Default, "ELm.", env, obj, mid); /* TODO: args! */ \
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001397 sc.CheckSig(mid, _retsig, false); \
1398 sc.CheckVirtualMethod(obj, mid); \
Elliott Hughesa2501992011-08-26 19:39:54 -07001399 _retdecl; \
Elliott Hughesba8eee12012-01-24 20:25:24 -08001400 _retasgn(baseEnv(env)->Call##_jname##MethodV(env, obj, mid, args)); \
Elliott Hughesa2501992011-08-26 19:39:54 -07001401 _retok; \
1402 } \
1403 static _ctype Call##_jname##MethodA(JNIEnv* env, jobject obj, \
1404 jmethodID mid, jvalue* args) \
1405 { \
1406 CHECK_JNI_ENTRY(kFlag_Default, "ELm.", env, obj, mid); /* TODO: args! */ \
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001407 sc.CheckSig(mid, _retsig, false); \
1408 sc.CheckVirtualMethod(obj, mid); \
Elliott Hughesa2501992011-08-26 19:39:54 -07001409 _retdecl; \
Elliott Hughesba8eee12012-01-24 20:25:24 -08001410 _retasgn(baseEnv(env)->Call##_jname##MethodA(env, obj, mid, args)); \
Elliott Hughesa2501992011-08-26 19:39:54 -07001411 _retok; \
1412 } \
1413 /* Non-virtual... */ \
1414 static _ctype CallNonvirtual##_jname##Method(JNIEnv* env, \
Elliott Hughese84278b2012-03-22 10:06:53 -07001415 jobject obj, jclass c, jmethodID mid, ...) \
Elliott Hughesa2501992011-08-26 19:39:54 -07001416 { \
Elliott Hughese84278b2012-03-22 10:06:53 -07001417 CHECK_JNI_ENTRY(kFlag_Default, "ELcm.", env, obj, c, mid); /* TODO: args! */ \
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001418 sc.CheckSig(mid, _retsig, false); \
1419 sc.CheckVirtualMethod(obj, mid); \
Elliott Hughesa2501992011-08-26 19:39:54 -07001420 _retdecl; \
1421 va_list args; \
1422 va_start(args, mid); \
Elliott Hughese84278b2012-03-22 10:06:53 -07001423 _retasgn(baseEnv(env)->CallNonvirtual##_jname##MethodV(env, obj, c, mid, args)); \
Elliott Hughesa2501992011-08-26 19:39:54 -07001424 va_end(args); \
1425 _retok; \
1426 } \
1427 static _ctype CallNonvirtual##_jname##MethodV(JNIEnv* env, \
Elliott Hughese84278b2012-03-22 10:06:53 -07001428 jobject obj, jclass c, jmethodID mid, va_list args) \
Elliott Hughesa2501992011-08-26 19:39:54 -07001429 { \
Elliott Hughese84278b2012-03-22 10:06:53 -07001430 CHECK_JNI_ENTRY(kFlag_Default, "ELcm.", env, obj, c, mid); /* TODO: args! */ \
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001431 sc.CheckSig(mid, _retsig, false); \
1432 sc.CheckVirtualMethod(obj, mid); \
Elliott Hughesa2501992011-08-26 19:39:54 -07001433 _retdecl; \
Elliott Hughese84278b2012-03-22 10:06:53 -07001434 _retasgn(baseEnv(env)->CallNonvirtual##_jname##MethodV(env, obj, c, mid, args)); \
Elliott Hughesa2501992011-08-26 19:39:54 -07001435 _retok; \
1436 } \
1437 static _ctype CallNonvirtual##_jname##MethodA(JNIEnv* env, \
Elliott Hughese84278b2012-03-22 10:06:53 -07001438 jobject obj, jclass c, jmethodID mid, jvalue* args) \
Elliott Hughesa2501992011-08-26 19:39:54 -07001439 { \
Elliott Hughese84278b2012-03-22 10:06:53 -07001440 CHECK_JNI_ENTRY(kFlag_Default, "ELcm.", env, obj, c, mid); /* TODO: args! */ \
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001441 sc.CheckSig(mid, _retsig, false); \
1442 sc.CheckVirtualMethod(obj, mid); \
Elliott Hughesa2501992011-08-26 19:39:54 -07001443 _retdecl; \
Elliott Hughese84278b2012-03-22 10:06:53 -07001444 _retasgn(baseEnv(env)->CallNonvirtual##_jname##MethodA(env, obj, c, mid, args)); \
Elliott Hughesa2501992011-08-26 19:39:54 -07001445 _retok; \
1446 } \
1447 /* Static... */ \
Elliott Hughese84278b2012-03-22 10:06:53 -07001448 static _ctype CallStatic##_jname##Method(JNIEnv* env, jclass c, jmethodID mid, ...) \
Elliott Hughesa2501992011-08-26 19:39:54 -07001449 { \
Elliott Hughese84278b2012-03-22 10:06:53 -07001450 CHECK_JNI_ENTRY(kFlag_Default, "Ecm.", env, c, mid); /* TODO: args! */ \
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001451 sc.CheckSig(mid, _retsig, true); \
Elliott Hughese84278b2012-03-22 10:06:53 -07001452 sc.CheckStaticMethod(c, mid); \
Elliott Hughesa2501992011-08-26 19:39:54 -07001453 _retdecl; \
1454 va_list args; \
1455 va_start(args, mid); \
Elliott Hughese84278b2012-03-22 10:06:53 -07001456 _retasgn(baseEnv(env)->CallStatic##_jname##MethodV(env, c, mid, args)); \
Elliott Hughesa2501992011-08-26 19:39:54 -07001457 va_end(args); \
1458 _retok; \
1459 } \
Elliott Hughese84278b2012-03-22 10:06:53 -07001460 static _ctype CallStatic##_jname##MethodV(JNIEnv* env, jclass c, jmethodID mid, va_list args) \
Elliott Hughesa2501992011-08-26 19:39:54 -07001461 { \
Elliott Hughese84278b2012-03-22 10:06:53 -07001462 CHECK_JNI_ENTRY(kFlag_Default, "Ecm.", env, c, mid); /* TODO: args! */ \
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001463 sc.CheckSig(mid, _retsig, true); \
Elliott Hughese84278b2012-03-22 10:06:53 -07001464 sc.CheckStaticMethod(c, mid); \
Elliott Hughesa2501992011-08-26 19:39:54 -07001465 _retdecl; \
Elliott Hughese84278b2012-03-22 10:06:53 -07001466 _retasgn(baseEnv(env)->CallStatic##_jname##MethodV(env, c, mid, args)); \
Elliott Hughesa2501992011-08-26 19:39:54 -07001467 _retok; \
1468 } \
Elliott Hughese84278b2012-03-22 10:06:53 -07001469 static _ctype CallStatic##_jname##MethodA(JNIEnv* env, jclass c, jmethodID mid, jvalue* args) \
Elliott Hughesa2501992011-08-26 19:39:54 -07001470 { \
Elliott Hughese84278b2012-03-22 10:06:53 -07001471 CHECK_JNI_ENTRY(kFlag_Default, "Ecm.", env, c, mid); /* TODO: args! */ \
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001472 sc.CheckSig(mid, _retsig, true); \
Elliott Hughese84278b2012-03-22 10:06:53 -07001473 sc.CheckStaticMethod(c, mid); \
Elliott Hughesa2501992011-08-26 19:39:54 -07001474 _retdecl; \
Elliott Hughese84278b2012-03-22 10:06:53 -07001475 _retasgn(baseEnv(env)->CallStatic##_jname##MethodA(env, c, mid, args)); \
Elliott Hughesa2501992011-08-26 19:39:54 -07001476 _retok; \
1477 }
1478
1479#define NON_VOID_RETURN(_retsig, _ctype) return CHECK_JNI_EXIT(_retsig, (_ctype) result)
1480#define VOID_RETURN CHECK_JNI_EXIT_VOID()
1481
Ian Rogers2dd0e2c2013-01-24 12:42:14 -08001482CALL(jobject, Object, mirror::Object* result, result = reinterpret_cast<mirror::Object*>, NON_VOID_RETURN("L", jobject), "L");
Elliott Hughesba8eee12012-01-24 20:25:24 -08001483CALL(jboolean, Boolean, jboolean result, result =, NON_VOID_RETURN("Z", jboolean), "Z");
1484CALL(jbyte, Byte, jbyte result, result =, NON_VOID_RETURN("B", jbyte), "B");
1485CALL(jchar, Char, jchar result, result =, NON_VOID_RETURN("C", jchar), "C");
1486CALL(jshort, Short, jshort result, result =, NON_VOID_RETURN("S", jshort), "S");
1487CALL(jint, Int, jint result, result =, NON_VOID_RETURN("I", jint), "I");
1488CALL(jlong, Long, jlong result, result =, NON_VOID_RETURN("J", jlong), "J");
1489CALL(jfloat, Float, jfloat result, result =, NON_VOID_RETURN("F", jfloat), "F");
1490CALL(jdouble, Double, jdouble result, result =, NON_VOID_RETURN("D", jdouble), "D");
Elliott Hughesa2501992011-08-26 19:39:54 -07001491CALL(void, Void, , , VOID_RETURN, "V");
1492
1493 static jstring NewString(JNIEnv* env, const jchar* unicodeChars, jsize len) {
1494 CHECK_JNI_ENTRY(kFlag_Default, "Epz", env, unicodeChars, len);
1495 return CHECK_JNI_EXIT("s", baseEnv(env)->NewString(env, unicodeChars, len));
1496 }
1497
1498 static jsize GetStringLength(JNIEnv* env, jstring string) {
1499 CHECK_JNI_ENTRY(kFlag_CritOkay, "Es", env, string);
1500 return CHECK_JNI_EXIT("I", baseEnv(env)->GetStringLength(env, string));
1501 }
1502
1503 static const jchar* GetStringChars(JNIEnv* env, jstring java_string, jboolean* isCopy) {
1504 CHECK_JNI_ENTRY(kFlag_CritOkay, "Esp", env, java_string, isCopy);
1505 const jchar* result = baseEnv(env)->GetStringChars(env, java_string, isCopy);
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001506 if (sc.ForceCopy() && result != NULL) {
Ian Rogers2dd0e2c2013-01-24 12:42:14 -08001507 mirror::String* s = sc.soa().Decode<mirror::String*>(java_string);
Elliott Hughesa2501992011-08-26 19:39:54 -07001508 int byteCount = s->GetLength() * 2;
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001509 result = (const jchar*) GuardedCopy::Create(result, byteCount, false);
Elliott Hughesa2501992011-08-26 19:39:54 -07001510 if (isCopy != NULL) {
1511 *isCopy = JNI_TRUE;
1512 }
1513 }
1514 return CHECK_JNI_EXIT("p", result);
1515 }
1516
1517 static void ReleaseStringChars(JNIEnv* env, jstring string, const jchar* chars) {
1518 CHECK_JNI_ENTRY(kFlag_Default | kFlag_ExcepOkay, "Esp", env, string, chars);
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001519 sc.CheckNonNull(chars);
1520 if (sc.ForceCopy()) {
1521 GuardedCopy::Check(__FUNCTION__, chars, false);
Elliott Hughesba8eee12012-01-24 20:25:24 -08001522 chars = reinterpret_cast<const jchar*>(GuardedCopy::Destroy(const_cast<jchar*>(chars)));
Elliott Hughesa2501992011-08-26 19:39:54 -07001523 }
1524 baseEnv(env)->ReleaseStringChars(env, string, chars);
1525 CHECK_JNI_EXIT_VOID();
1526 }
1527
1528 static jstring NewStringUTF(JNIEnv* env, const char* bytes) {
1529 CHECK_JNI_ENTRY(kFlag_NullableUtf, "Eu", env, bytes); // TODO: show pointer and truncate string.
1530 return CHECK_JNI_EXIT("s", baseEnv(env)->NewStringUTF(env, bytes));
1531 }
1532
1533 static jsize GetStringUTFLength(JNIEnv* env, jstring string) {
1534 CHECK_JNI_ENTRY(kFlag_CritOkay, "Es", env, string);
1535 return CHECK_JNI_EXIT("I", baseEnv(env)->GetStringUTFLength(env, string));
1536 }
1537
1538 static const char* GetStringUTFChars(JNIEnv* env, jstring string, jboolean* isCopy) {
1539 CHECK_JNI_ENTRY(kFlag_CritOkay, "Esp", env, string, isCopy);
1540 const char* result = baseEnv(env)->GetStringUTFChars(env, string, isCopy);
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001541 if (sc.ForceCopy() && result != NULL) {
1542 result = (const char*) GuardedCopy::Create(result, strlen(result) + 1, false);
Elliott Hughesa2501992011-08-26 19:39:54 -07001543 if (isCopy != NULL) {
1544 *isCopy = JNI_TRUE;
1545 }
1546 }
1547 return CHECK_JNI_EXIT("u", result); // TODO: show pointer and truncate string.
1548 }
1549
1550 static void ReleaseStringUTFChars(JNIEnv* env, jstring string, const char* utf) {
1551 CHECK_JNI_ENTRY(kFlag_ExcepOkay | kFlag_Release, "Esu", env, string, utf); // TODO: show pointer and truncate string.
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001552 if (sc.ForceCopy()) {
1553 GuardedCopy::Check(__FUNCTION__, utf, false);
Elliott Hughesba8eee12012-01-24 20:25:24 -08001554 utf = reinterpret_cast<const char*>(GuardedCopy::Destroy(const_cast<char*>(utf)));
Elliott Hughesa2501992011-08-26 19:39:54 -07001555 }
1556 baseEnv(env)->ReleaseStringUTFChars(env, string, utf);
1557 CHECK_JNI_EXIT_VOID();
1558 }
1559
1560 static jsize GetArrayLength(JNIEnv* env, jarray array) {
1561 CHECK_JNI_ENTRY(kFlag_CritOkay, "Ea", env, array);
1562 return CHECK_JNI_EXIT("I", baseEnv(env)->GetArrayLength(env, array));
1563 }
1564
1565 static jobjectArray NewObjectArray(JNIEnv* env, jsize length, jclass elementClass, jobject initialElement) {
1566 CHECK_JNI_ENTRY(kFlag_Default, "EzcL", env, length, elementClass, initialElement);
1567 return CHECK_JNI_EXIT("a", baseEnv(env)->NewObjectArray(env, length, elementClass, initialElement));
1568 }
1569
1570 static jobject GetObjectArrayElement(JNIEnv* env, jobjectArray array, jsize index) {
1571 CHECK_JNI_ENTRY(kFlag_Default, "EaI", env, array, index);
1572 return CHECK_JNI_EXIT("L", baseEnv(env)->GetObjectArrayElement(env, array, index));
1573 }
1574
1575 static void SetObjectArrayElement(JNIEnv* env, jobjectArray array, jsize index, jobject value) {
1576 CHECK_JNI_ENTRY(kFlag_Default, "EaIL", env, array, index, value);
1577 baseEnv(env)->SetObjectArrayElement(env, array, index, value);
1578 CHECK_JNI_EXIT_VOID();
1579 }
1580
1581#define NEW_PRIMITIVE_ARRAY(_artype, _jname) \
1582 static _artype New##_jname##Array(JNIEnv* env, jsize length) { \
1583 CHECK_JNI_ENTRY(kFlag_Default, "Ez", env, length); \
1584 return CHECK_JNI_EXIT("a", baseEnv(env)->New##_jname##Array(env, length)); \
1585 }
1586NEW_PRIMITIVE_ARRAY(jbooleanArray, Boolean);
1587NEW_PRIMITIVE_ARRAY(jbyteArray, Byte);
1588NEW_PRIMITIVE_ARRAY(jcharArray, Char);
1589NEW_PRIMITIVE_ARRAY(jshortArray, Short);
1590NEW_PRIMITIVE_ARRAY(jintArray, Int);
1591NEW_PRIMITIVE_ARRAY(jlongArray, Long);
1592NEW_PRIMITIVE_ARRAY(jfloatArray, Float);
1593NEW_PRIMITIVE_ARRAY(jdoubleArray, Double);
1594
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001595struct ForceCopyGetChecker {
Elliott Hughesba8eee12012-01-24 20:25:24 -08001596 public:
Elliott Hughesa2501992011-08-26 19:39:54 -07001597 ForceCopyGetChecker(ScopedCheck& sc, jboolean* isCopy) {
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001598 force_copy = sc.ForceCopy();
1599 no_copy = 0;
1600 if (force_copy && isCopy != NULL) {
Elliott Hughes3f6635a2012-06-19 13:37:49 -07001601 // Capture this before the base call tramples on it.
Elliott Hughesba8eee12012-01-24 20:25:24 -08001602 no_copy = *reinterpret_cast<uint32_t*>(isCopy);
Elliott Hughesa2501992011-08-26 19:39:54 -07001603 }
1604 }
1605
1606 template<typename ResultT>
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001607 ResultT Check(JNIEnv* env, jarray array, jboolean* isCopy, ResultT result) {
1608 if (force_copy && result != NULL) {
1609 if (no_copy != kNoCopyMagic) {
Elliott Hughesa2501992011-08-26 19:39:54 -07001610 result = reinterpret_cast<ResultT>(CreateGuardedPACopy(env, array, isCopy));
1611 }
1612 }
1613 return result;
1614 }
1615
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001616 uint32_t no_copy;
1617 bool force_copy;
Elliott Hughesa2501992011-08-26 19:39:54 -07001618};
1619
1620#define GET_PRIMITIVE_ARRAY_ELEMENTS(_ctype, _jname) \
1621 static _ctype* Get##_jname##ArrayElements(JNIEnv* env, _ctype##Array array, jboolean* isCopy) { \
1622 CHECK_JNI_ENTRY(kFlag_Default, "Eap", env, array, isCopy); \
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001623 _ctype* result = ForceCopyGetChecker(sc, isCopy).Check(env, array, isCopy, baseEnv(env)->Get##_jname##ArrayElements(env, array, isCopy)); \
Elliott Hughesa2501992011-08-26 19:39:54 -07001624 return CHECK_JNI_EXIT("p", result); \
1625 }
1626
1627#define RELEASE_PRIMITIVE_ARRAY_ELEMENTS(_ctype, _jname) \
1628 static void Release##_jname##ArrayElements(JNIEnv* env, _ctype##Array array, _ctype* elems, jint mode) { \
1629 CHECK_JNI_ENTRY(kFlag_Default | kFlag_ExcepOkay, "Eapr", env, array, elems, mode); \
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001630 sc.CheckNonNull(elems); \
1631 if (sc.ForceCopy()) { \
Elliott Hughesa2501992011-08-26 19:39:54 -07001632 ReleaseGuardedPACopy(env, array, elems, mode); \
1633 } \
1634 baseEnv(env)->Release##_jname##ArrayElements(env, array, elems, mode); \
1635 CHECK_JNI_EXIT_VOID(); \
1636 }
1637
1638#define GET_PRIMITIVE_ARRAY_REGION(_ctype, _jname) \
1639 static void Get##_jname##ArrayRegion(JNIEnv* env, _ctype##Array array, jsize start, jsize len, _ctype* buf) { \
1640 CHECK_JNI_ENTRY(kFlag_Default, "EaIIp", env, array, start, len, buf); \
1641 baseEnv(env)->Get##_jname##ArrayRegion(env, array, start, len, buf); \
1642 CHECK_JNI_EXIT_VOID(); \
1643 }
1644
1645#define SET_PRIMITIVE_ARRAY_REGION(_ctype, _jname) \
1646 static void Set##_jname##ArrayRegion(JNIEnv* env, _ctype##Array array, jsize start, jsize len, const _ctype* buf) { \
1647 CHECK_JNI_ENTRY(kFlag_Default, "EaIIp", env, array, start, len, buf); \
1648 baseEnv(env)->Set##_jname##ArrayRegion(env, array, start, len, buf); \
1649 CHECK_JNI_EXIT_VOID(); \
1650 }
1651
1652#define PRIMITIVE_ARRAY_FUNCTIONS(_ctype, _jname, _typechar) \
1653 GET_PRIMITIVE_ARRAY_ELEMENTS(_ctype, _jname); \
1654 RELEASE_PRIMITIVE_ARRAY_ELEMENTS(_ctype, _jname); \
1655 GET_PRIMITIVE_ARRAY_REGION(_ctype, _jname); \
1656 SET_PRIMITIVE_ARRAY_REGION(_ctype, _jname);
1657
Elliott Hughes3f6635a2012-06-19 13:37:49 -07001658// TODO: verify primitive array type matches call type.
Elliott Hughesa2501992011-08-26 19:39:54 -07001659PRIMITIVE_ARRAY_FUNCTIONS(jboolean, Boolean, 'Z');
1660PRIMITIVE_ARRAY_FUNCTIONS(jbyte, Byte, 'B');
1661PRIMITIVE_ARRAY_FUNCTIONS(jchar, Char, 'C');
1662PRIMITIVE_ARRAY_FUNCTIONS(jshort, Short, 'S');
1663PRIMITIVE_ARRAY_FUNCTIONS(jint, Int, 'I');
1664PRIMITIVE_ARRAY_FUNCTIONS(jlong, Long, 'J');
1665PRIMITIVE_ARRAY_FUNCTIONS(jfloat, Float, 'F');
1666PRIMITIVE_ARRAY_FUNCTIONS(jdouble, Double, 'D');
1667
Elliott Hughese84278b2012-03-22 10:06:53 -07001668 static jint RegisterNatives(JNIEnv* env, jclass c, const JNINativeMethod* methods, jint nMethods) {
1669 CHECK_JNI_ENTRY(kFlag_Default, "EcpI", env, c, methods, nMethods);
1670 return CHECK_JNI_EXIT("I", baseEnv(env)->RegisterNatives(env, c, methods, nMethods));
Elliott Hughesa2501992011-08-26 19:39:54 -07001671 }
1672
Elliott Hughese84278b2012-03-22 10:06:53 -07001673 static jint UnregisterNatives(JNIEnv* env, jclass c) {
1674 CHECK_JNI_ENTRY(kFlag_Default, "Ec", env, c);
1675 return CHECK_JNI_EXIT("I", baseEnv(env)->UnregisterNatives(env, c));
Elliott Hughesa2501992011-08-26 19:39:54 -07001676 }
1677
1678 static jint MonitorEnter(JNIEnv* env, jobject obj) {
1679 CHECK_JNI_ENTRY(kFlag_Default, "EL", env, obj);
Elliott Hughesa92853e2012-02-07 16:09:27 -08001680 if (!sc.CheckInstance(ScopedCheck::kObject, obj)) {
1681 return JNI_ERR; // Only for jni_internal_test. Real code will have aborted already.
1682 }
Elliott Hughesa2501992011-08-26 19:39:54 -07001683 return CHECK_JNI_EXIT("I", baseEnv(env)->MonitorEnter(env, obj));
1684 }
1685
1686 static jint MonitorExit(JNIEnv* env, jobject obj) {
1687 CHECK_JNI_ENTRY(kFlag_Default | kFlag_ExcepOkay, "EL", env, obj);
Elliott Hughesa92853e2012-02-07 16:09:27 -08001688 if (!sc.CheckInstance(ScopedCheck::kObject, obj)) {
1689 return JNI_ERR; // Only for jni_internal_test. Real code will have aborted already.
1690 }
Elliott Hughesa2501992011-08-26 19:39:54 -07001691 return CHECK_JNI_EXIT("I", baseEnv(env)->MonitorExit(env, obj));
1692 }
1693
1694 static jint GetJavaVM(JNIEnv *env, JavaVM **vm) {
1695 CHECK_JNI_ENTRY(kFlag_Default, "Ep", env, vm);
1696 return CHECK_JNI_EXIT("I", baseEnv(env)->GetJavaVM(env, vm));
1697 }
1698
1699 static void GetStringRegion(JNIEnv* env, jstring str, jsize start, jsize len, jchar* buf) {
1700 CHECK_JNI_ENTRY(kFlag_CritOkay, "EsIIp", env, str, start, len, buf);
1701 baseEnv(env)->GetStringRegion(env, str, start, len, buf);
1702 CHECK_JNI_EXIT_VOID();
1703 }
1704
1705 static void GetStringUTFRegion(JNIEnv* env, jstring str, jsize start, jsize len, char* buf) {
1706 CHECK_JNI_ENTRY(kFlag_CritOkay, "EsIIp", env, str, start, len, buf);
1707 baseEnv(env)->GetStringUTFRegion(env, str, start, len, buf);
1708 CHECK_JNI_EXIT_VOID();
1709 }
1710
1711 static void* GetPrimitiveArrayCritical(JNIEnv* env, jarray array, jboolean* isCopy) {
1712 CHECK_JNI_ENTRY(kFlag_CritGet, "Eap", env, array, isCopy);
1713 void* result = baseEnv(env)->GetPrimitiveArrayCritical(env, array, isCopy);
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001714 if (sc.ForceCopy() && result != NULL) {
Elliott Hughesa2501992011-08-26 19:39:54 -07001715 result = CreateGuardedPACopy(env, array, isCopy);
1716 }
1717 return CHECK_JNI_EXIT("p", result);
1718 }
1719
1720 static void ReleasePrimitiveArrayCritical(JNIEnv* env, jarray array, void* carray, jint mode) {
1721 CHECK_JNI_ENTRY(kFlag_CritRelease | kFlag_ExcepOkay, "Eapr", env, array, carray, mode);
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001722 sc.CheckNonNull(carray);
1723 if (sc.ForceCopy()) {
Elliott Hughesa2501992011-08-26 19:39:54 -07001724 ReleaseGuardedPACopy(env, array, carray, mode);
1725 }
1726 baseEnv(env)->ReleasePrimitiveArrayCritical(env, array, carray, mode);
1727 CHECK_JNI_EXIT_VOID();
1728 }
1729
1730 static const jchar* GetStringCritical(JNIEnv* env, jstring java_string, jboolean* isCopy) {
1731 CHECK_JNI_ENTRY(kFlag_CritGet, "Esp", env, java_string, isCopy);
1732 const jchar* result = baseEnv(env)->GetStringCritical(env, java_string, isCopy);
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001733 if (sc.ForceCopy() && result != NULL) {
Ian Rogers2dd0e2c2013-01-24 12:42:14 -08001734 mirror::String* s = sc.soa().Decode<mirror::String*>(java_string);
Elliott Hughesa2501992011-08-26 19:39:54 -07001735 int byteCount = s->GetLength() * 2;
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001736 result = (const jchar*) GuardedCopy::Create(result, byteCount, false);
Elliott Hughesa2501992011-08-26 19:39:54 -07001737 if (isCopy != NULL) {
1738 *isCopy = JNI_TRUE;
1739 }
1740 }
1741 return CHECK_JNI_EXIT("p", result);
1742 }
1743
1744 static void ReleaseStringCritical(JNIEnv* env, jstring string, const jchar* carray) {
1745 CHECK_JNI_ENTRY(kFlag_CritRelease | kFlag_ExcepOkay, "Esp", env, string, carray);
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001746 sc.CheckNonNull(carray);
1747 if (sc.ForceCopy()) {
1748 GuardedCopy::Check(__FUNCTION__, carray, false);
Elliott Hughesba8eee12012-01-24 20:25:24 -08001749 carray = reinterpret_cast<const jchar*>(GuardedCopy::Destroy(const_cast<jchar*>(carray)));
Elliott Hughesa2501992011-08-26 19:39:54 -07001750 }
1751 baseEnv(env)->ReleaseStringCritical(env, string, carray);
1752 CHECK_JNI_EXIT_VOID();
1753 }
1754
1755 static jweak NewWeakGlobalRef(JNIEnv* env, jobject obj) {
1756 CHECK_JNI_ENTRY(kFlag_Default, "EL", env, obj);
1757 return CHECK_JNI_EXIT("L", baseEnv(env)->NewWeakGlobalRef(env, obj));
1758 }
1759
1760 static jboolean ExceptionCheck(JNIEnv* env) {
1761 CHECK_JNI_ENTRY(kFlag_CritOkay | kFlag_ExcepOkay, "E", env);
1762 return CHECK_JNI_EXIT("b", baseEnv(env)->ExceptionCheck(env));
1763 }
1764
1765 static jobjectRefType GetObjectRefType(JNIEnv* env, jobject obj) {
1766 // Note: we use "Ep" rather than "EL" because this is the one JNI function
1767 // that it's okay to pass an invalid reference to.
1768 CHECK_JNI_ENTRY(kFlag_Default, "Ep", env, obj);
1769 // TODO: proper decoding of jobjectRefType!
1770 return CHECK_JNI_EXIT("I", baseEnv(env)->GetObjectRefType(env, obj));
1771 }
1772
1773 static jobject NewDirectByteBuffer(JNIEnv* env, void* address, jlong capacity) {
1774 CHECK_JNI_ENTRY(kFlag_Default, "EpJ", env, address, capacity);
1775 if (address == NULL) {
Elliott Hughes3f6635a2012-06-19 13:37:49 -07001776 JniAbortF(__FUNCTION__, "non-nullable address is NULL");
Elliott Hughesa2501992011-08-26 19:39:54 -07001777 }
1778 if (capacity <= 0) {
Ian Rogers62d6c772013-02-27 08:32:07 -08001779 JniAbortF(__FUNCTION__, "capacity must be greater than 0: %lld", capacity);
Elliott Hughesa2501992011-08-26 19:39:54 -07001780 }
1781 return CHECK_JNI_EXIT("L", baseEnv(env)->NewDirectByteBuffer(env, address, capacity));
1782 }
1783
1784 static void* GetDirectBufferAddress(JNIEnv* env, jobject buf) {
1785 CHECK_JNI_ENTRY(kFlag_Default, "EL", env, buf);
1786 // TODO: check that 'buf' is a java.nio.Buffer.
1787 return CHECK_JNI_EXIT("p", baseEnv(env)->GetDirectBufferAddress(env, buf));
1788 }
1789
1790 static jlong GetDirectBufferCapacity(JNIEnv* env, jobject buf) {
1791 CHECK_JNI_ENTRY(kFlag_Default, "EL", env, buf);
1792 // TODO: check that 'buf' is a java.nio.Buffer.
1793 return CHECK_JNI_EXIT("J", baseEnv(env)->GetDirectBufferCapacity(env, buf));
1794 }
1795
1796 private:
1797 static inline const JNINativeInterface* baseEnv(JNIEnv* env) {
1798 return reinterpret_cast<JNIEnvExt*>(env)->unchecked_functions;
1799 }
1800};
1801
1802const JNINativeInterface gCheckNativeInterface = {
1803 NULL, // reserved0.
1804 NULL, // reserved1.
1805 NULL, // reserved2.
1806 NULL, // reserved3.
1807 CheckJNI::GetVersion,
1808 CheckJNI::DefineClass,
1809 CheckJNI::FindClass,
1810 CheckJNI::FromReflectedMethod,
1811 CheckJNI::FromReflectedField,
1812 CheckJNI::ToReflectedMethod,
1813 CheckJNI::GetSuperclass,
1814 CheckJNI::IsAssignableFrom,
1815 CheckJNI::ToReflectedField,
1816 CheckJNI::Throw,
1817 CheckJNI::ThrowNew,
1818 CheckJNI::ExceptionOccurred,
1819 CheckJNI::ExceptionDescribe,
1820 CheckJNI::ExceptionClear,
1821 CheckJNI::FatalError,
1822 CheckJNI::PushLocalFrame,
1823 CheckJNI::PopLocalFrame,
1824 CheckJNI::NewGlobalRef,
1825 CheckJNI::DeleteGlobalRef,
1826 CheckJNI::DeleteLocalRef,
1827 CheckJNI::IsSameObject,
1828 CheckJNI::NewLocalRef,
1829 CheckJNI::EnsureLocalCapacity,
1830 CheckJNI::AllocObject,
1831 CheckJNI::NewObject,
1832 CheckJNI::NewObjectV,
1833 CheckJNI::NewObjectA,
1834 CheckJNI::GetObjectClass,
1835 CheckJNI::IsInstanceOf,
1836 CheckJNI::GetMethodID,
1837 CheckJNI::CallObjectMethod,
1838 CheckJNI::CallObjectMethodV,
1839 CheckJNI::CallObjectMethodA,
1840 CheckJNI::CallBooleanMethod,
1841 CheckJNI::CallBooleanMethodV,
1842 CheckJNI::CallBooleanMethodA,
1843 CheckJNI::CallByteMethod,
1844 CheckJNI::CallByteMethodV,
1845 CheckJNI::CallByteMethodA,
1846 CheckJNI::CallCharMethod,
1847 CheckJNI::CallCharMethodV,
1848 CheckJNI::CallCharMethodA,
1849 CheckJNI::CallShortMethod,
1850 CheckJNI::CallShortMethodV,
1851 CheckJNI::CallShortMethodA,
1852 CheckJNI::CallIntMethod,
1853 CheckJNI::CallIntMethodV,
1854 CheckJNI::CallIntMethodA,
1855 CheckJNI::CallLongMethod,
1856 CheckJNI::CallLongMethodV,
1857 CheckJNI::CallLongMethodA,
1858 CheckJNI::CallFloatMethod,
1859 CheckJNI::CallFloatMethodV,
1860 CheckJNI::CallFloatMethodA,
1861 CheckJNI::CallDoubleMethod,
1862 CheckJNI::CallDoubleMethodV,
1863 CheckJNI::CallDoubleMethodA,
1864 CheckJNI::CallVoidMethod,
1865 CheckJNI::CallVoidMethodV,
1866 CheckJNI::CallVoidMethodA,
1867 CheckJNI::CallNonvirtualObjectMethod,
1868 CheckJNI::CallNonvirtualObjectMethodV,
1869 CheckJNI::CallNonvirtualObjectMethodA,
1870 CheckJNI::CallNonvirtualBooleanMethod,
1871 CheckJNI::CallNonvirtualBooleanMethodV,
1872 CheckJNI::CallNonvirtualBooleanMethodA,
1873 CheckJNI::CallNonvirtualByteMethod,
1874 CheckJNI::CallNonvirtualByteMethodV,
1875 CheckJNI::CallNonvirtualByteMethodA,
1876 CheckJNI::CallNonvirtualCharMethod,
1877 CheckJNI::CallNonvirtualCharMethodV,
1878 CheckJNI::CallNonvirtualCharMethodA,
1879 CheckJNI::CallNonvirtualShortMethod,
1880 CheckJNI::CallNonvirtualShortMethodV,
1881 CheckJNI::CallNonvirtualShortMethodA,
1882 CheckJNI::CallNonvirtualIntMethod,
1883 CheckJNI::CallNonvirtualIntMethodV,
1884 CheckJNI::CallNonvirtualIntMethodA,
1885 CheckJNI::CallNonvirtualLongMethod,
1886 CheckJNI::CallNonvirtualLongMethodV,
1887 CheckJNI::CallNonvirtualLongMethodA,
1888 CheckJNI::CallNonvirtualFloatMethod,
1889 CheckJNI::CallNonvirtualFloatMethodV,
1890 CheckJNI::CallNonvirtualFloatMethodA,
1891 CheckJNI::CallNonvirtualDoubleMethod,
1892 CheckJNI::CallNonvirtualDoubleMethodV,
1893 CheckJNI::CallNonvirtualDoubleMethodA,
1894 CheckJNI::CallNonvirtualVoidMethod,
1895 CheckJNI::CallNonvirtualVoidMethodV,
1896 CheckJNI::CallNonvirtualVoidMethodA,
1897 CheckJNI::GetFieldID,
1898 CheckJNI::GetObjectField,
1899 CheckJNI::GetBooleanField,
1900 CheckJNI::GetByteField,
1901 CheckJNI::GetCharField,
1902 CheckJNI::GetShortField,
1903 CheckJNI::GetIntField,
1904 CheckJNI::GetLongField,
1905 CheckJNI::GetFloatField,
1906 CheckJNI::GetDoubleField,
1907 CheckJNI::SetObjectField,
1908 CheckJNI::SetBooleanField,
1909 CheckJNI::SetByteField,
1910 CheckJNI::SetCharField,
1911 CheckJNI::SetShortField,
1912 CheckJNI::SetIntField,
1913 CheckJNI::SetLongField,
1914 CheckJNI::SetFloatField,
1915 CheckJNI::SetDoubleField,
1916 CheckJNI::GetStaticMethodID,
1917 CheckJNI::CallStaticObjectMethod,
1918 CheckJNI::CallStaticObjectMethodV,
1919 CheckJNI::CallStaticObjectMethodA,
1920 CheckJNI::CallStaticBooleanMethod,
1921 CheckJNI::CallStaticBooleanMethodV,
1922 CheckJNI::CallStaticBooleanMethodA,
1923 CheckJNI::CallStaticByteMethod,
1924 CheckJNI::CallStaticByteMethodV,
1925 CheckJNI::CallStaticByteMethodA,
1926 CheckJNI::CallStaticCharMethod,
1927 CheckJNI::CallStaticCharMethodV,
1928 CheckJNI::CallStaticCharMethodA,
1929 CheckJNI::CallStaticShortMethod,
1930 CheckJNI::CallStaticShortMethodV,
1931 CheckJNI::CallStaticShortMethodA,
1932 CheckJNI::CallStaticIntMethod,
1933 CheckJNI::CallStaticIntMethodV,
1934 CheckJNI::CallStaticIntMethodA,
1935 CheckJNI::CallStaticLongMethod,
1936 CheckJNI::CallStaticLongMethodV,
1937 CheckJNI::CallStaticLongMethodA,
1938 CheckJNI::CallStaticFloatMethod,
1939 CheckJNI::CallStaticFloatMethodV,
1940 CheckJNI::CallStaticFloatMethodA,
1941 CheckJNI::CallStaticDoubleMethod,
1942 CheckJNI::CallStaticDoubleMethodV,
1943 CheckJNI::CallStaticDoubleMethodA,
1944 CheckJNI::CallStaticVoidMethod,
1945 CheckJNI::CallStaticVoidMethodV,
1946 CheckJNI::CallStaticVoidMethodA,
1947 CheckJNI::GetStaticFieldID,
1948 CheckJNI::GetStaticObjectField,
1949 CheckJNI::GetStaticBooleanField,
1950 CheckJNI::GetStaticByteField,
1951 CheckJNI::GetStaticCharField,
1952 CheckJNI::GetStaticShortField,
1953 CheckJNI::GetStaticIntField,
1954 CheckJNI::GetStaticLongField,
1955 CheckJNI::GetStaticFloatField,
1956 CheckJNI::GetStaticDoubleField,
1957 CheckJNI::SetStaticObjectField,
1958 CheckJNI::SetStaticBooleanField,
1959 CheckJNI::SetStaticByteField,
1960 CheckJNI::SetStaticCharField,
1961 CheckJNI::SetStaticShortField,
1962 CheckJNI::SetStaticIntField,
1963 CheckJNI::SetStaticLongField,
1964 CheckJNI::SetStaticFloatField,
1965 CheckJNI::SetStaticDoubleField,
1966 CheckJNI::NewString,
1967 CheckJNI::GetStringLength,
1968 CheckJNI::GetStringChars,
1969 CheckJNI::ReleaseStringChars,
1970 CheckJNI::NewStringUTF,
1971 CheckJNI::GetStringUTFLength,
1972 CheckJNI::GetStringUTFChars,
1973 CheckJNI::ReleaseStringUTFChars,
1974 CheckJNI::GetArrayLength,
1975 CheckJNI::NewObjectArray,
1976 CheckJNI::GetObjectArrayElement,
1977 CheckJNI::SetObjectArrayElement,
1978 CheckJNI::NewBooleanArray,
1979 CheckJNI::NewByteArray,
1980 CheckJNI::NewCharArray,
1981 CheckJNI::NewShortArray,
1982 CheckJNI::NewIntArray,
1983 CheckJNI::NewLongArray,
1984 CheckJNI::NewFloatArray,
1985 CheckJNI::NewDoubleArray,
1986 CheckJNI::GetBooleanArrayElements,
1987 CheckJNI::GetByteArrayElements,
1988 CheckJNI::GetCharArrayElements,
1989 CheckJNI::GetShortArrayElements,
1990 CheckJNI::GetIntArrayElements,
1991 CheckJNI::GetLongArrayElements,
1992 CheckJNI::GetFloatArrayElements,
1993 CheckJNI::GetDoubleArrayElements,
1994 CheckJNI::ReleaseBooleanArrayElements,
1995 CheckJNI::ReleaseByteArrayElements,
1996 CheckJNI::ReleaseCharArrayElements,
1997 CheckJNI::ReleaseShortArrayElements,
1998 CheckJNI::ReleaseIntArrayElements,
1999 CheckJNI::ReleaseLongArrayElements,
2000 CheckJNI::ReleaseFloatArrayElements,
2001 CheckJNI::ReleaseDoubleArrayElements,
2002 CheckJNI::GetBooleanArrayRegion,
2003 CheckJNI::GetByteArrayRegion,
2004 CheckJNI::GetCharArrayRegion,
2005 CheckJNI::GetShortArrayRegion,
2006 CheckJNI::GetIntArrayRegion,
2007 CheckJNI::GetLongArrayRegion,
2008 CheckJNI::GetFloatArrayRegion,
2009 CheckJNI::GetDoubleArrayRegion,
2010 CheckJNI::SetBooleanArrayRegion,
2011 CheckJNI::SetByteArrayRegion,
2012 CheckJNI::SetCharArrayRegion,
2013 CheckJNI::SetShortArrayRegion,
2014 CheckJNI::SetIntArrayRegion,
2015 CheckJNI::SetLongArrayRegion,
2016 CheckJNI::SetFloatArrayRegion,
2017 CheckJNI::SetDoubleArrayRegion,
2018 CheckJNI::RegisterNatives,
2019 CheckJNI::UnregisterNatives,
2020 CheckJNI::MonitorEnter,
2021 CheckJNI::MonitorExit,
2022 CheckJNI::GetJavaVM,
2023 CheckJNI::GetStringRegion,
2024 CheckJNI::GetStringUTFRegion,
2025 CheckJNI::GetPrimitiveArrayCritical,
2026 CheckJNI::ReleasePrimitiveArrayCritical,
2027 CheckJNI::GetStringCritical,
2028 CheckJNI::ReleaseStringCritical,
2029 CheckJNI::NewWeakGlobalRef,
2030 CheckJNI::DeleteWeakGlobalRef,
2031 CheckJNI::ExceptionCheck,
2032 CheckJNI::NewDirectByteBuffer,
2033 CheckJNI::GetDirectBufferAddress,
2034 CheckJNI::GetDirectBufferCapacity,
2035 CheckJNI::GetObjectRefType,
2036};
2037
2038const JNINativeInterface* GetCheckJniNativeInterface() {
2039 return &gCheckNativeInterface;
2040}
2041
2042class CheckJII {
Elliott Hughesba8eee12012-01-24 20:25:24 -08002043 public:
Elliott Hughesa2501992011-08-26 19:39:54 -07002044 static jint DestroyJavaVM(JavaVM* vm) {
Elliott Hughesa0957642011-09-02 14:27:33 -07002045 ScopedCheck sc(vm, false, __FUNCTION__);
Elliott Hughes32ae6e32011-09-27 10:46:50 -07002046 sc.Check(true, "v", vm);
2047 return CHECK_JNI_EXIT("I", BaseVm(vm)->DestroyJavaVM(vm));
Elliott Hughesa2501992011-08-26 19:39:54 -07002048 }
2049
2050 static jint AttachCurrentThread(JavaVM* vm, JNIEnv** p_env, void* thr_args) {
Elliott Hughesa0957642011-09-02 14:27:33 -07002051 ScopedCheck sc(vm, false, __FUNCTION__);
Elliott Hughes32ae6e32011-09-27 10:46:50 -07002052 sc.Check(true, "vpp", vm, p_env, thr_args);
2053 return CHECK_JNI_EXIT("I", BaseVm(vm)->AttachCurrentThread(vm, p_env, thr_args));
Elliott Hughesa2501992011-08-26 19:39:54 -07002054 }
2055
2056 static jint AttachCurrentThreadAsDaemon(JavaVM* vm, JNIEnv** p_env, void* thr_args) {
Elliott Hughesa0957642011-09-02 14:27:33 -07002057 ScopedCheck sc(vm, false, __FUNCTION__);
Elliott Hughes32ae6e32011-09-27 10:46:50 -07002058 sc.Check(true, "vpp", vm, p_env, thr_args);
2059 return CHECK_JNI_EXIT("I", BaseVm(vm)->AttachCurrentThreadAsDaemon(vm, p_env, thr_args));
Elliott Hughesa2501992011-08-26 19:39:54 -07002060 }
2061
2062 static jint DetachCurrentThread(JavaVM* vm) {
Elliott Hughesa0957642011-09-02 14:27:33 -07002063 ScopedCheck sc(vm, true, __FUNCTION__);
Elliott Hughes32ae6e32011-09-27 10:46:50 -07002064 sc.Check(true, "v", vm);
2065 return CHECK_JNI_EXIT("I", BaseVm(vm)->DetachCurrentThread(vm));
Elliott Hughesa2501992011-08-26 19:39:54 -07002066 }
2067
2068 static jint GetEnv(JavaVM* vm, void** env, jint version) {
Elliott Hughesa0957642011-09-02 14:27:33 -07002069 ScopedCheck sc(vm, true, __FUNCTION__);
Elliott Hughes83a25322013-03-14 11:18:53 -07002070 sc.Check(true, "vpI", vm);
Elliott Hughes32ae6e32011-09-27 10:46:50 -07002071 return CHECK_JNI_EXIT("I", BaseVm(vm)->GetEnv(vm, env, version));
Elliott Hughesa2501992011-08-26 19:39:54 -07002072 }
2073
2074 private:
Elliott Hughes32ae6e32011-09-27 10:46:50 -07002075 static inline const JNIInvokeInterface* BaseVm(JavaVM* vm) {
Elliott Hughesa2501992011-08-26 19:39:54 -07002076 return reinterpret_cast<JavaVMExt*>(vm)->unchecked_functions;
2077 }
2078};
2079
2080const JNIInvokeInterface gCheckInvokeInterface = {
2081 NULL, // reserved0
2082 NULL, // reserved1
2083 NULL, // reserved2
2084 CheckJII::DestroyJavaVM,
2085 CheckJII::AttachCurrentThread,
2086 CheckJII::DetachCurrentThread,
2087 CheckJII::GetEnv,
2088 CheckJII::AttachCurrentThreadAsDaemon
2089};
2090
2091const JNIInvokeInterface* GetCheckJniInvokeInterface() {
2092 return &gCheckInvokeInterface;
2093}
2094
2095} // namespace art