blob: 47f20e19d54cdc064c203a5fcc9b4caf73cc159d [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
22#include "class_linker.h"
23#include "logging.h"
Ian Rogers6d4d9fc2011-11-30 16:24:48 -080024#include "object_utils.h"
Elliott Hughesc5bfa8f2011-08-30 14:32:49 -070025#include "scoped_jni_thread_state.h"
Elliott Hughesb3bd5f02012-03-08 21:05:27 -080026#include "space.h"
Elliott Hughesa2501992011-08-26 19:39:54 -070027#include "thread.h"
Brian Carlstrom1f870082011-08-23 16:02:11 -070028#include "runtime.h"
Elliott Hughesa2501992011-08-26 19:39:54 -070029
Elliott Hughese6087632011-09-26 12:18:25 -070030#define LIBCORE_CPP_JNI_HELPERS
31#include <JNIHelp.h> // from libcore
32#undef LIBCORE_CPP_JNI_HELPERS
33
Elliott Hughesa2501992011-08-26 19:39:54 -070034namespace art {
35
Elliott Hughes3f6635a2012-06-19 13:37:49 -070036static void JniAbort(const char* jni_function_name, const char* msg) {
Elliott Hughesa0957642011-09-02 14:27:33 -070037 Thread* self = Thread::Current();
Elliott Hughesd07986f2011-12-06 18:27:45 -080038 Method* current_method = self->GetCurrentMethod();
Elliott Hughesa2501992011-08-26 19:39:54 -070039
Elliott Hughes3b6baaa2011-10-14 19:13:56 -070040 std::ostringstream os;
Elliott Hughes3f6635a2012-06-19 13:37:49 -070041 os << "JNI DETECTED ERROR IN APPLICATION: " << msg;
Elliott Hughesa2501992011-08-26 19:39:54 -070042
43 if (jni_function_name != NULL) {
Elliott Hughes3f6635a2012-06-19 13:37:49 -070044 os << "\n in call to " << jni_function_name;
Elliott Hughesa2501992011-08-26 19:39:54 -070045 }
Elliott Hughesa0957642011-09-02 14:27:33 -070046 // TODO: is this useful given that we're about to dump the calling thread's stack?
47 if (current_method != NULL) {
Elliott Hughes3f6635a2012-06-19 13:37:49 -070048 os << "\n from " << PrettyMethod(current_method);
Elliott Hughesa0957642011-09-02 14:27:33 -070049 }
50 os << "\n";
51 self->Dump(os);
Elliott Hughesa2501992011-08-26 19:39:54 -070052
53 JavaVMExt* vm = Runtime::Current()->GetJavaVM();
54 if (vm->check_jni_abort_hook != NULL) {
Elliott Hughesb264f082012-04-06 17:10:10 -070055 vm->check_jni_abort_hook(vm->check_jni_abort_hook_data, os.str());
Elliott Hughesa2501992011-08-26 19:39:54 -070056 } else {
Elliott Hughes34e06962012-04-09 13:55:55 -070057 self->SetState(kNative); // Ensure that we get a native stack trace for this thread.
Elliott Hughesa2501992011-08-26 19:39:54 -070058 LOG(FATAL) << os.str();
59 }
60}
61
Elliott Hughes3f6635a2012-06-19 13:37:49 -070062static void JniAbortV(const char* jni_function_name, const char* fmt, va_list ap) {
63 std::string msg;
64 StringAppendV(&msg, fmt, ap);
65 JniAbort(jni_function_name, msg.c_str());
66}
67
68void JniAbortF(const char* jni_function_name, const char* fmt, ...) {
69 va_list args;
70 va_start(args, fmt);
71 JniAbortV(jni_function_name, fmt, args);
72 va_end(args);
73}
74
Elliott Hughesa2501992011-08-26 19:39:54 -070075/*
76 * ===========================================================================
77 * JNI function helpers
78 * ===========================================================================
79 */
80
Ian Rogers959f8ed2012-02-07 16:33:37 -080081static bool IsSirtLocalRef(JNIEnv* env, jobject localRef) {
82 return GetIndirectRefKind(localRef) == kSirtOrInvalid &&
Ian Rogers0399dde2012-06-06 17:09:28 -070083 reinterpret_cast<JNIEnvExt*>(env)->self->SirtContains(localRef);
Ian Rogers959f8ed2012-02-07 16:33:37 -080084}
85
Elliott Hughes3f6635a2012-06-19 13:37:49 -070086// Hack to allow forcecopy to work with jniGetNonMovableArrayElements.
87// The code deliberately uses an invalid sequence of operations, so we
88// need to pass it through unmodified. Review that code before making
89// any changes here.
Elliott Hughesa2501992011-08-26 19:39:54 -070090#define kNoCopyMagic 0xd5aab57f
91
Elliott Hughes3f6635a2012-06-19 13:37:49 -070092// Flags passed into ScopedCheck.
Elliott Hughesa2501992011-08-26 19:39:54 -070093#define kFlag_Default 0x0000
94
Elliott Hughes3f6635a2012-06-19 13:37:49 -070095#define kFlag_CritBad 0x0000 // Calling while in critical is not allowed.
96#define kFlag_CritOkay 0x0001 // Calling while in critical is allowed.
97#define kFlag_CritGet 0x0002 // This is a critical "get".
98#define kFlag_CritRelease 0x0003 // This is a critical "release".
99#define kFlag_CritMask 0x0003 // Bit mask to get "crit" value.
Elliott Hughesa2501992011-08-26 19:39:54 -0700100
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700101#define kFlag_ExcepBad 0x0000 // Raised exceptions are not allowed.
102#define kFlag_ExcepOkay 0x0004 // Raised exceptions are allowed.
Elliott Hughesa2501992011-08-26 19:39:54 -0700103
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700104#define kFlag_Release 0x0010 // Are we in a non-critical release function?
105#define kFlag_NullableUtf 0x0020 // Are our UTF parameters nullable?
Elliott Hughesa2501992011-08-26 19:39:54 -0700106
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700107#define kFlag_Invocation 0x8000 // Part of the invocation interface (JavaVM*).
Elliott Hughesa2501992011-08-26 19:39:54 -0700108
Elliott Hughes485cac42011-12-09 17:49:35 -0800109#define kFlag_ForceTrace 0x80000000 // Add this to a JNI function's flags if you want to trace every call.
110
Elliott Hughesa0957642011-09-02 14:27:33 -0700111static const char* gBuiltInPrefixes[] = {
112 "Landroid/",
113 "Lcom/android/",
114 "Lcom/google/android/",
115 "Ldalvik/",
116 "Ljava/",
117 "Ljavax/",
118 "Llibcore/",
119 "Lorg/apache/harmony/",
120 NULL
121};
122
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700123static bool ShouldTrace(JavaVMExt* vm, const Method* method) {
Elliott Hughesa0957642011-09-02 14:27:33 -0700124 // If both "-Xcheck:jni" and "-Xjnitrace:" are enabled, we print trace messages
125 // when a native method that matches the -Xjnitrace argument calls a JNI function
126 // such as NewByteArray.
127 // If -verbose:third-party-jni is on, we want to log any JNI function calls
128 // made by a third-party native method.
Elliott Hughes81ff3182012-03-23 20:35:56 -0700129 std::string class_name(MethodHelper(method).GetDeclaringClassDescriptor());
130 if (!vm->trace.empty() && class_name.find(vm->trace) != std::string::npos) {
Elliott Hughesa0957642011-09-02 14:27:33 -0700131 return true;
132 }
Elliott Hughes4dd9b4d2011-12-12 18:29:24 -0800133 if (VLOG_IS_ON(third_party_jni)) {
Elliott Hughesa0957642011-09-02 14:27:33 -0700134 // Return true if we're trying to log all third-party JNI activity and 'method' doesn't look
135 // like part of Android.
Elliott Hughesa0957642011-09-02 14:27:33 -0700136 for (size_t i = 0; gBuiltInPrefixes[i] != NULL; ++i) {
Elliott Hughes81ff3182012-03-23 20:35:56 -0700137 if (StartsWith(class_name, gBuiltInPrefixes[i])) {
Elliott Hughesa0957642011-09-02 14:27:33 -0700138 return false;
139 }
140 }
141 return true;
142 }
143 return false;
144}
145
Elliott Hughesa2501992011-08-26 19:39:54 -0700146class ScopedCheck {
Elliott Hughesba8eee12012-01-24 20:25:24 -0800147 public:
Elliott Hughesa2501992011-08-26 19:39:54 -0700148 // For JNIEnv* functions.
Ian Rogers365c1022012-06-22 15:05:28 -0700149 explicit ScopedCheck(JNIEnv* env, int flags, const char* functionName) : ts_(env) {
150 Init(flags, functionName, true);
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700151 CheckThread(flags);
Elliott Hughesa2501992011-08-26 19:39:54 -0700152 }
153
154 // For JavaVM* functions.
Ian Rogers365c1022012-06-22 15:05:28 -0700155 explicit ScopedCheck(JavaVM* vm, bool has_method, const char* functionName) : ts_(vm) {
156 Init(kFlag_Invocation, functionName, has_method);
Elliott Hughesa2501992011-08-26 19:39:54 -0700157 }
158
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700159 bool ForceCopy() {
Elliott Hughesa2501992011-08-26 19:39:54 -0700160 return Runtime::Current()->GetJavaVM()->force_copy;
161 }
162
Elliott Hughes81ff3182012-03-23 20:35:56 -0700163 // Checks that 'class_name' is a valid "fully-qualified" JNI class name, like "java/lang/Thread"
164 // or "[Ljava/lang/Object;". A ClassLoader can actually normalize class names a couple of
165 // times, so using "java.lang.Thread" instead of "java/lang/Thread" might work in some
166 // circumstances, but this is incorrect.
167 void CheckClassName(const char* class_name) {
168 if (!IsValidJniClassName(class_name)) {
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700169 JniAbortF(function_name_,
170 "illegal class name '%s'\n"
171 " (should be of the form 'package/Class', [Lpackage/Class;' or '[[B')",
172 class_name);
Elliott Hughesa2501992011-08-26 19:39:54 -0700173 }
174 }
175
176 /*
177 * Verify that the field is of the appropriate type. If the field has an
178 * object type, "java_object" is the object we're trying to assign into it.
179 *
180 * Works for both static and instance fields.
181 */
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700182 void CheckFieldType(jobject java_object, jfieldID fid, char prim, bool isStatic) {
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700183 Field* f = CheckFieldID(fid);
184 if (f == NULL) {
Elliott Hughesa2501992011-08-26 19:39:54 -0700185 return;
186 }
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800187 Class* field_type = FieldHelper(f).GetType();
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700188 if (!field_type->IsPrimitive()) {
189 if (java_object != NULL) {
Ian Rogers365c1022012-06-22 15:05:28 -0700190 Object* obj = ts_.Decode<Object*>(java_object);
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700191 // If java_object is a weak global ref whose referent has been cleared,
192 // obj will be NULL. Otherwise, obj should always be non-NULL
193 // and valid.
Elliott Hughes88c5c352012-03-15 18:49:48 -0700194 if (!Runtime::Current()->GetHeap()->IsHeapAddress(obj)) {
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700195 JniAbortF(function_name_, "field operation on invalid %s: %p",
196 ToStr<IndirectRefKind>(GetIndirectRefKind(java_object)).c_str(), java_object);
Elliott Hughesa2501992011-08-26 19:39:54 -0700197 return;
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700198 } else {
Brian Carlstrom16192862011-09-12 17:50:06 -0700199 if (!obj->InstanceOf(field_type)) {
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700200 JniAbortF(function_name_, "attempt to set field %s with value of wrong type: %s",
201 PrettyField(f).c_str(), PrettyTypeOf(obj).c_str());
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700202 return;
203 }
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700204 }
Elliott Hughesa2501992011-08-26 19:39:54 -0700205 }
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700206 } else if (field_type != Runtime::Current()->GetClassLinker()->FindPrimitiveClass(prim)) {
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700207 JniAbortF(function_name_, "attempt to set field %s with value of wrong type: %c",
208 PrettyField(f).c_str(), prim);
Elliott Hughesa2501992011-08-26 19:39:54 -0700209 return;
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700210 }
211
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700212 if (isStatic != f->IsStatic()) {
Elliott Hughesa2501992011-08-26 19:39:54 -0700213 if (isStatic) {
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700214 JniAbortF(function_name_, "accessing non-static field %s as static", PrettyField(f).c_str());
Elliott Hughesa2501992011-08-26 19:39:54 -0700215 } else {
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700216 JniAbortF(function_name_, "accessing static field %s as non-static", PrettyField(f).c_str());
Elliott Hughesa2501992011-08-26 19:39:54 -0700217 }
Elliott Hughesa2501992011-08-26 19:39:54 -0700218 return;
219 }
220 }
221
222 /*
223 * Verify that this instance field ID is valid for this object.
224 *
225 * Assumes "jobj" has already been validated.
226 */
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700227 void CheckInstanceFieldID(jobject java_object, jfieldID fid) {
Ian Rogers365c1022012-06-22 15:05:28 -0700228 Object* o = ts_.Decode<Object*>(java_object);
Elliott Hughesb3bd5f02012-03-08 21:05:27 -0800229 if (o == NULL || !Runtime::Current()->GetHeap()->IsHeapAddress(o)) {
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700230 JniAbortF(function_name_, "field operation on invalid %s: %p",
231 ToStr<IndirectRefKind>(GetIndirectRefKind(java_object)).c_str(), java_object);
Elliott Hughesa2501992011-08-26 19:39:54 -0700232 return;
233 }
234
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700235 Field* f = CheckFieldID(fid);
236 if (f == NULL) {
237 return;
238 }
Elliott Hughesa2501992011-08-26 19:39:54 -0700239 Class* c = o->GetClass();
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800240 FieldHelper fh(f);
241 if (c->FindInstanceField(fh.GetName(), fh.GetTypeDescriptor()) == NULL) {
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700242 JniAbortF(function_name_, "jfieldID %s not valid for an object of class %s",
243 PrettyField(f).c_str(), PrettyTypeOf(o).c_str());
Elliott Hughesa2501992011-08-26 19:39:54 -0700244 }
245 }
246
247 /*
248 * Verify that the pointer value is non-NULL.
249 */
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700250 void CheckNonNull(const void* ptr) {
Elliott Hughesa2501992011-08-26 19:39:54 -0700251 if (ptr == NULL) {
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700252 JniAbortF(function_name_, "non-nullable argument was NULL");
Elliott Hughesa2501992011-08-26 19:39:54 -0700253 }
254 }
255
256 /*
257 * Verify that the method's return type matches the type of call.
258 * 'expectedType' will be "L" for all objects, including arrays.
259 */
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700260 void CheckSig(jmethodID mid, const char* expectedType, bool isStatic) {
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800261 Method* m = CheckMethodID(mid);
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700262 if (m == NULL) {
263 return;
264 }
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800265 if (*expectedType != MethodHelper(m).GetShorty()[0]) {
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700266 JniAbortF(function_name_, "the return type of %s does not match %s",
267 function_name_, PrettyMethod(m).c_str());
268 }
269 if (isStatic != m->IsStatic()) {
Elliott Hughesa2501992011-08-26 19:39:54 -0700270 if (isStatic) {
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700271 JniAbortF(function_name_, "calling non-static method %s with %s",
272 PrettyMethod(m).c_str(), function_name_);
Elliott Hughesa2501992011-08-26 19:39:54 -0700273 } else {
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700274 JniAbortF(function_name_, "calling static method %s with %s",
275 PrettyMethod(m).c_str(), function_name_);
Elliott Hughesa2501992011-08-26 19:39:54 -0700276 }
Elliott Hughesa2501992011-08-26 19:39:54 -0700277 }
278 }
279
280 /*
281 * Verify that this static field ID is valid for this class.
282 *
283 * Assumes "java_class" has already been validated.
284 */
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700285 void CheckStaticFieldID(jclass java_class, jfieldID fid) {
Ian Rogers365c1022012-06-22 15:05:28 -0700286 Class* c = ts_.Decode<Class*>(java_class);
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700287 const Field* f = CheckFieldID(fid);
288 if (f == NULL) {
289 return;
290 }
Elliott Hughesa2501992011-08-26 19:39:54 -0700291 if (f->GetDeclaringClass() != c) {
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700292 JniAbortF(function_name_, "static jfieldID %p not valid for class %s",
293 fid, PrettyClass(c).c_str());
Elliott Hughesa2501992011-08-26 19:39:54 -0700294 }
295 }
296
297 /*
Elliott Hughese84278b2012-03-22 10:06:53 -0700298 * Verify that "mid" is appropriate for "java_class".
Elliott Hughesa2501992011-08-26 19:39:54 -0700299 *
300 * A mismatch isn't dangerous, because the jmethodID defines the class. In
Elliott Hughese84278b2012-03-22 10:06:53 -0700301 * fact, java_class is unused in the implementation. It's best if we don't
Elliott Hughesa2501992011-08-26 19:39:54 -0700302 * allow bad code in the system though.
303 *
Elliott Hughese84278b2012-03-22 10:06:53 -0700304 * Instances of "java_class" must be instances of the method's declaring class.
Elliott Hughesa2501992011-08-26 19:39:54 -0700305 */
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700306 void CheckStaticMethod(jclass java_class, jmethodID mid) {
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700307 const Method* m = CheckMethodID(mid);
308 if (m == NULL) {
309 return;
310 }
Ian Rogers365c1022012-06-22 15:05:28 -0700311 Class* c = ts_.Decode<Class*>(java_class);
Elliott Hughesa2501992011-08-26 19:39:54 -0700312 if (!c->IsAssignableFrom(m->GetDeclaringClass())) {
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700313 JniAbortF(function_name_, "can't call static %s on class %s",
314 PrettyMethod(m).c_str(), PrettyClass(c).c_str());
Elliott Hughesa2501992011-08-26 19:39:54 -0700315 }
316 }
317
318 /*
319 * Verify that "mid" is appropriate for "jobj".
320 *
321 * Make sure the object is an instance of the method's declaring class.
322 * (Note the mid might point to a declaration in an interface; this
323 * will be handled automatically by the instanceof check.)
324 */
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700325 void CheckVirtualMethod(jobject java_object, jmethodID mid) {
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700326 const Method* m = CheckMethodID(mid);
327 if (m == NULL) {
328 return;
329 }
Ian Rogers365c1022012-06-22 15:05:28 -0700330 Object* o = ts_.Decode<Object*>(java_object);
Elliott Hughesa2501992011-08-26 19:39:54 -0700331 if (!o->InstanceOf(m->GetDeclaringClass())) {
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700332 JniAbortF(function_name_, "can't call %s on instance of %s",
333 PrettyMethod(m).c_str(), PrettyTypeOf(o).c_str());
Elliott Hughesa2501992011-08-26 19:39:54 -0700334 }
335 }
336
337 /**
338 * The format string is a sequence of the following characters,
339 * and must be followed by arguments of the corresponding types
340 * in the same order.
341 *
342 * Java primitive types:
343 * B - jbyte
344 * C - jchar
345 * D - jdouble
346 * F - jfloat
347 * I - jint
348 * J - jlong
349 * S - jshort
350 * Z - jboolean (shown as true and false)
351 * V - void
352 *
353 * Java reference types:
354 * L - jobject
355 * a - jarray
356 * c - jclass
357 * s - jstring
358 *
359 * JNI types:
360 * b - jboolean (shown as JNI_TRUE and JNI_FALSE)
361 * f - jfieldID
362 * m - jmethodID
363 * p - void*
364 * r - jint (for release mode arguments)
Elliott Hughes78090d12011-10-07 14:31:47 -0700365 * u - const char* (Modified UTF-8)
Elliott Hughesa2501992011-08-26 19:39:54 -0700366 * z - jsize (for lengths; use i if negative values are okay)
367 * v - JavaVM*
368 * E - JNIEnv*
369 * . - no argument; just print "..." (used for varargs JNI calls)
370 *
371 * Use the kFlag_NullableUtf flag where 'u' field(s) are nullable.
372 */
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700373 void Check(bool entry, const char* fmt0, ...) {
Elliott Hughesa2501992011-08-26 19:39:54 -0700374 va_list ap;
375
Elliott Hughesa0957642011-09-02 14:27:33 -0700376 const Method* traceMethod = NULL;
Ian Rogers365c1022012-06-22 15:05:28 -0700377 if ((!ts_.Vm()->trace.empty() || VLOG_IS_ON(third_party_jni)) && has_method_) {
Elliott Hughesa2501992011-08-26 19:39:54 -0700378 // We need to guard some of the invocation interface's calls: a bad caller might
379 // use DetachCurrentThread or GetEnv on a thread that's not yet attached.
Elliott Hughesa0957642011-09-02 14:27:33 -0700380 Thread* self = Thread::Current();
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700381 if ((flags_ & kFlag_Invocation) == 0 || self != NULL) {
Elliott Hughesa0957642011-09-02 14:27:33 -0700382 traceMethod = self->GetCurrentMethod();
Elliott Hughesa2501992011-08-26 19:39:54 -0700383 }
384 }
Elliott Hughesa0957642011-09-02 14:27:33 -0700385
Ian Rogers365c1022012-06-22 15:05:28 -0700386 if (((flags_ & kFlag_ForceTrace) != 0) || (traceMethod != NULL && ShouldTrace(ts_.Vm(), traceMethod))) {
Elliott Hughesa2501992011-08-26 19:39:54 -0700387 va_start(ap, fmt0);
388 std::string msg;
389 for (const char* fmt = fmt0; *fmt;) {
390 char ch = *fmt++;
391 if (ch == 'B') { // jbyte
392 jbyte b = va_arg(ap, int);
393 if (b >= 0 && b < 10) {
394 StringAppendF(&msg, "%d", b);
395 } else {
396 StringAppendF(&msg, "%#x (%d)", b, b);
397 }
398 } else if (ch == 'C') { // jchar
399 jchar c = va_arg(ap, int);
400 if (c < 0x7f && c >= ' ') {
401 StringAppendF(&msg, "U+%x ('%c')", c, c);
402 } else {
403 StringAppendF(&msg, "U+%x", c);
404 }
405 } else if (ch == 'F' || ch == 'D') { // jfloat, jdouble
406 StringAppendF(&msg, "%g", va_arg(ap, double));
407 } else if (ch == 'I' || ch == 'S') { // jint, jshort
408 StringAppendF(&msg, "%d", va_arg(ap, int));
409 } else if (ch == 'J') { // jlong
410 StringAppendF(&msg, "%lld", va_arg(ap, jlong));
411 } else if (ch == 'Z') { // jboolean
412 StringAppendF(&msg, "%s", va_arg(ap, int) ? "true" : "false");
413 } else if (ch == 'V') { // void
414 msg += "void";
415 } else if (ch == 'v') { // JavaVM*
416 JavaVM* vm = va_arg(ap, JavaVM*);
417 StringAppendF(&msg, "(JavaVM*)%p", vm);
418 } else if (ch == 'E') { // JNIEnv*
419 JNIEnv* env = va_arg(ap, JNIEnv*);
420 StringAppendF(&msg, "(JNIEnv*)%p", env);
421 } else if (ch == 'L' || ch == 'a' || ch == 's') { // jobject, jarray, jstring
422 // For logging purposes, these are identical.
423 jobject o = va_arg(ap, jobject);
424 if (o == NULL) {
425 msg += "NULL";
426 } else {
427 StringAppendF(&msg, "%p", o);
428 }
429 } else if (ch == 'b') { // jboolean (JNI-style)
430 jboolean b = va_arg(ap, int);
431 msg += (b ? "JNI_TRUE" : "JNI_FALSE");
432 } else if (ch == 'c') { // jclass
433 jclass jc = va_arg(ap, jclass);
434 Class* c = reinterpret_cast<Class*>(Thread::Current()->DecodeJObject(jc));
435 if (c == NULL) {
436 msg += "NULL";
Elliott Hughesb3bd5f02012-03-08 21:05:27 -0800437 } else if (c == kInvalidIndirectRefObject || !Runtime::Current()->GetHeap()->IsHeapAddress(c)) {
Elliott Hughes485cac42011-12-09 17:49:35 -0800438 StringAppendF(&msg, "INVALID POINTER:%p", jc);
439 } else if (!c->IsClass()) {
440 msg += "INVALID NON-CLASS OBJECT OF TYPE:" + PrettyTypeOf(c);
Elliott Hughesa2501992011-08-26 19:39:54 -0700441 } else {
Elliott Hughes54e7df12011-09-16 11:47:04 -0700442 msg += PrettyClass(c);
Elliott Hughesa2501992011-08-26 19:39:54 -0700443 if (!entry) {
444 StringAppendF(&msg, " (%p)", jc);
445 }
446 }
447 } else if (ch == 'f') { // jfieldID
448 jfieldID fid = va_arg(ap, jfieldID);
Elliott Hughes5ee7a8b2011-09-13 16:40:07 -0700449 Field* f = reinterpret_cast<Field*>(fid);
Elliott Hughesa2501992011-08-26 19:39:54 -0700450 msg += PrettyField(f);
451 if (!entry) {
452 StringAppendF(&msg, " (%p)", fid);
453 }
454 } else if (ch == 'z') { // non-negative jsize
455 // You might expect jsize to be size_t, but it's not; it's the same as jint.
456 // We only treat this specially so we can do the non-negative check.
457 // TODO: maybe this wasn't worth it?
458 jint i = va_arg(ap, jint);
459 StringAppendF(&msg, "%d", i);
460 } else if (ch == 'm') { // jmethodID
461 jmethodID mid = va_arg(ap, jmethodID);
Elliott Hughes5ee7a8b2011-09-13 16:40:07 -0700462 Method* m = reinterpret_cast<Method*>(mid);
Elliott Hughesa2501992011-08-26 19:39:54 -0700463 msg += PrettyMethod(m);
464 if (!entry) {
465 StringAppendF(&msg, " (%p)", mid);
466 }
467 } else if (ch == 'p') { // void* ("pointer")
468 void* p = va_arg(ap, void*);
469 if (p == NULL) {
470 msg += "NULL";
471 } else {
472 StringAppendF(&msg, "(void*) %p", p);
473 }
474 } else if (ch == 'r') { // jint (release mode)
475 jint releaseMode = va_arg(ap, jint);
476 if (releaseMode == 0) {
477 msg += "0";
478 } else if (releaseMode == JNI_ABORT) {
479 msg += "JNI_ABORT";
480 } else if (releaseMode == JNI_COMMIT) {
481 msg += "JNI_COMMIT";
482 } else {
483 StringAppendF(&msg, "invalid release mode %d", releaseMode);
484 }
Elliott Hughes78090d12011-10-07 14:31:47 -0700485 } else if (ch == 'u') { // const char* (Modified UTF-8)
Elliott Hughesa2501992011-08-26 19:39:54 -0700486 const char* utf = va_arg(ap, const char*);
487 if (utf == NULL) {
488 msg += "NULL";
489 } else {
490 StringAppendF(&msg, "\"%s\"", utf);
491 }
492 } else if (ch == '.') {
493 msg += "...";
494 } else {
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700495 JniAbortF(function_name_, "unknown trace format specifier: %c", ch);
Elliott Hughesa2501992011-08-26 19:39:54 -0700496 return;
497 }
498 if (*fmt) {
499 StringAppendF(&msg, ", ");
500 }
501 }
502 va_end(ap);
503
Elliott Hughes485cac42011-12-09 17:49:35 -0800504 if ((flags_ & kFlag_ForceTrace) != 0) {
505 LOG(INFO) << "JNI: call to " << function_name_ << "(" << msg << ")";
506 } else if (entry) {
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700507 if (has_method_) {
Elliott Hughesa0957642011-09-02 14:27:33 -0700508 std::string methodName(PrettyMethod(traceMethod, false));
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700509 LOG(INFO) << "JNI: " << methodName << " -> " << function_name_ << "(" << msg << ")";
510 indent_ = methodName.size() + 1;
Elliott Hughesa2501992011-08-26 19:39:54 -0700511 } else {
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700512 LOG(INFO) << "JNI: -> " << function_name_ << "(" << msg << ")";
513 indent_ = 0;
Elliott Hughesa2501992011-08-26 19:39:54 -0700514 }
515 } else {
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700516 LOG(INFO) << StringPrintf("JNI: %*s<- %s returned %s", indent_, "", function_name_, msg.c_str());
Elliott Hughesa2501992011-08-26 19:39:54 -0700517 }
518 }
519
520 // We always do the thorough checks on entry, and never on exit...
521 if (entry) {
522 va_start(ap, fmt0);
523 for (const char* fmt = fmt0; *fmt; ++fmt) {
524 char ch = *fmt;
525 if (ch == 'a') {
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700526 CheckArray(va_arg(ap, jarray));
Elliott Hughesa2501992011-08-26 19:39:54 -0700527 } else if (ch == 'c') {
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700528 CheckInstance(kClass, va_arg(ap, jclass));
Elliott Hughesa2501992011-08-26 19:39:54 -0700529 } else if (ch == 'L') {
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700530 CheckObject(va_arg(ap, jobject));
Elliott Hughesa2501992011-08-26 19:39:54 -0700531 } else if (ch == 'r') {
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700532 CheckReleaseMode(va_arg(ap, jint));
Elliott Hughesa2501992011-08-26 19:39:54 -0700533 } else if (ch == 's') {
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700534 CheckInstance(kString, va_arg(ap, jstring));
Elliott Hughesa2501992011-08-26 19:39:54 -0700535 } else if (ch == 'u') {
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700536 if ((flags_ & kFlag_Release) != 0) {
537 CheckNonNull(va_arg(ap, const char*));
Elliott Hughesa2501992011-08-26 19:39:54 -0700538 } else {
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700539 bool nullable = ((flags_ & kFlag_NullableUtf) != 0);
540 CheckUtfString(va_arg(ap, const char*), nullable);
Elliott Hughesa2501992011-08-26 19:39:54 -0700541 }
542 } else if (ch == 'z') {
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700543 CheckLengthPositive(va_arg(ap, jsize));
Elliott Hughesa2501992011-08-26 19:39:54 -0700544 } else if (strchr("BCISZbfmpEv", ch) != NULL) {
Elliott Hughesba8eee12012-01-24 20:25:24 -0800545 va_arg(ap, uint32_t); // Skip this argument.
Elliott Hughesa2501992011-08-26 19:39:54 -0700546 } else if (ch == 'D' || ch == 'F') {
547 va_arg(ap, double); // Skip this argument.
548 } else if (ch == 'J') {
Elliott Hughesba8eee12012-01-24 20:25:24 -0800549 va_arg(ap, uint64_t); // Skip this argument.
Elliott Hughesa2501992011-08-26 19:39:54 -0700550 } else if (ch == '.') {
551 } else {
Elliott Hughes3d30d9b2011-12-07 17:35:48 -0800552 LOG(FATAL) << "Unknown check format specifier: " << ch;
Elliott Hughesa2501992011-08-26 19:39:54 -0700553 }
554 }
555 va_end(ap);
556 }
557 }
558
Elliott Hughesa92853e2012-02-07 16:09:27 -0800559 enum InstanceKind {
560 kClass,
Elliott Hughes0f3c5532012-03-30 14:51:51 -0700561 kDirectByteBuffer,
562 kObject,
563 kString,
564 kThrowable,
Elliott Hughesa92853e2012-02-07 16:09:27 -0800565 };
566
567 /*
568 * Verify that "jobj" is a valid non-NULL object reference, and points to
569 * an instance of expectedClass.
570 *
571 * Because we're looking at an object on the GC heap, we have to switch
572 * to "running" mode before doing the checks.
573 */
574 bool CheckInstance(InstanceKind kind, jobject java_object) {
575 const char* what = NULL;
576 switch (kind) {
577 case kClass:
578 what = "jclass";
579 break;
580 case kDirectByteBuffer:
581 what = "direct ByteBuffer";
582 break;
583 case kObject:
584 what = "jobject";
585 break;
586 case kString:
587 what = "jstring";
588 break;
589 case kThrowable:
590 what = "jthrowable";
591 break;
592 default:
Elliott Hughes7b9d9962012-04-20 18:48:18 -0700593 LOG(FATAL) << "Unknown kind " << static_cast<int>(kind);
Elliott Hughesa92853e2012-02-07 16:09:27 -0800594 }
595
596 if (java_object == NULL) {
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700597 JniAbortF(function_name_, "%s received null %s", function_name_, what);
Elliott Hughesa92853e2012-02-07 16:09:27 -0800598 return false;
599 }
600
Ian Rogers365c1022012-06-22 15:05:28 -0700601 Object* obj = ts_.Decode<Object*>(java_object);
Elliott Hughesb3bd5f02012-03-08 21:05:27 -0800602 if (!Runtime::Current()->GetHeap()->IsHeapAddress(obj)) {
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700603 JniAbortF(function_name_, "%s is an invalid %s: %p (%p)",
604 what, ToStr<IndirectRefKind>(GetIndirectRefKind(java_object)).c_str(), java_object, obj);
Elliott Hughesa92853e2012-02-07 16:09:27 -0800605 return false;
606 }
607
608 bool okay = true;
609 switch (kind) {
610 case kClass:
611 okay = obj->IsClass();
612 break;
613 case kDirectByteBuffer:
614 UNIMPLEMENTED(FATAL);
615 break;
616 case kString:
617 okay = obj->GetClass()->IsStringClass();
618 break;
619 case kThrowable:
620 okay = obj->GetClass()->IsThrowableClass();
621 break;
622 case kObject:
623 break;
624 }
625 if (!okay) {
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700626 JniAbortF(function_name_, "%s has wrong type: %s", what, PrettyTypeOf(obj).c_str());
Elliott Hughesa92853e2012-02-07 16:09:27 -0800627 return false;
628 }
629
630 return true;
631 }
632
Elliott Hughesba8eee12012-01-24 20:25:24 -0800633 private:
Elliott Hughes81ff3182012-03-23 20:35:56 -0700634 // Set "has_method" to true if we have a valid thread with a method pointer.
635 // We won't have one before attaching a thread, after detaching a thread, or
636 // when shutting down the runtime.
Ian Rogers365c1022012-06-22 15:05:28 -0700637 void Init(int flags, const char* functionName, bool has_method) {
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700638 flags_ = flags;
639 function_name_ = functionName;
Elliott Hughes81ff3182012-03-23 20:35:56 -0700640 has_method_ = has_method;
Elliott Hughesa2501992011-08-26 19:39:54 -0700641 }
642
643 /*
644 * Verify that "array" is non-NULL and points to an Array object.
645 *
646 * Since we're dealing with objects, switch to "running" mode.
647 */
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700648 void CheckArray(jarray java_array) {
Elliott Hughesa2501992011-08-26 19:39:54 -0700649 if (java_array == NULL) {
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700650 JniAbortF(function_name_, "jarray was NULL");
Elliott Hughesa2501992011-08-26 19:39:54 -0700651 return;
652 }
653
Ian Rogers365c1022012-06-22 15:05:28 -0700654 Array* a = ts_.Decode<Array*>(java_array);
Elliott Hughesb3bd5f02012-03-08 21:05:27 -0800655 if (!Runtime::Current()->GetHeap()->IsHeapAddress(a)) {
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700656 JniAbortF(function_name_, "jarray is an invalid %s: %p (%p)",
657 ToStr<IndirectRefKind>(GetIndirectRefKind(java_array)).c_str(), java_array, a);
Elliott Hughesa2501992011-08-26 19:39:54 -0700658 } else if (!a->IsArrayInstance()) {
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700659 JniAbortF(function_name_, "jarray argument has non-array type: %s", PrettyTypeOf(a).c_str());
Elliott Hughesa2501992011-08-26 19:39:54 -0700660 }
661 }
662
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700663 void CheckLengthPositive(jsize length) {
Elliott Hughesa2501992011-08-26 19:39:54 -0700664 if (length < 0) {
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700665 JniAbortF(function_name_, "negative jsize: %d", length);
Elliott Hughesa2501992011-08-26 19:39:54 -0700666 }
667 }
668
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700669 Field* CheckFieldID(jfieldID fid) {
670 if (fid == NULL) {
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700671 JniAbortF(function_name_, "jfieldID was NULL");
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700672 return NULL;
673 }
Ian Rogers365c1022012-06-22 15:05:28 -0700674 Field* f = ts_.DecodeField(fid);
675 if (!Runtime::Current()->GetHeap()->IsHeapAddress(f) || !f->IsField()) {
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700676 JniAbortF(function_name_, "invalid jfieldID: %p", fid);
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700677 return NULL;
678 }
679 return f;
680 }
681
682 Method* CheckMethodID(jmethodID mid) {
683 if (mid == NULL) {
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700684 JniAbortF(function_name_, "jmethodID was NULL");
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700685 return NULL;
686 }
Ian Rogers365c1022012-06-22 15:05:28 -0700687 Method* m = ts_.DecodeMethod(mid);
688 if (!Runtime::Current()->GetHeap()->IsHeapAddress(m) || !m->IsMethod()) {
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700689 JniAbortF(function_name_, "invalid jmethodID: %p", mid);
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700690 return NULL;
691 }
692 return m;
693 }
694
Elliott Hughesa2501992011-08-26 19:39:54 -0700695 /*
696 * Verify that "jobj" is a valid object, and that it's an object that JNI
697 * is allowed to know about. We allow NULL references.
698 *
699 * Switches to "running" mode before performing checks.
700 */
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700701 void CheckObject(jobject java_object) {
Elliott Hughesa2501992011-08-26 19:39:54 -0700702 if (java_object == NULL) {
703 return;
704 }
705
Ian Rogers365c1022012-06-22 15:05:28 -0700706 Object* o = ts_.Decode<Object*>(java_object);
Elliott Hughes88c5c352012-03-15 18:49:48 -0700707 if (!Runtime::Current()->GetHeap()->IsHeapAddress(o)) {
Elliott Hughesc5bfa8f2011-08-30 14:32:49 -0700708 // TODO: when we remove work_around_app_jni_bugs, this should be impossible.
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700709 JniAbortF(function_name_, "native code passing in reference to invalid %s: %p",
710 ToStr<IndirectRefKind>(GetIndirectRefKind(java_object)).c_str(), java_object);
Elliott Hughesa2501992011-08-26 19:39:54 -0700711 }
712 }
713
714 /*
715 * Verify that the "mode" argument passed to a primitive array Release
716 * function is one of the valid values.
717 */
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700718 void CheckReleaseMode(jint mode) {
Elliott Hughesa2501992011-08-26 19:39:54 -0700719 if (mode != 0 && mode != JNI_COMMIT && mode != JNI_ABORT) {
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700720 JniAbortF(function_name_, "bad value for release mode: %d", mode);
Elliott Hughesa2501992011-08-26 19:39:54 -0700721 }
722 }
723
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700724 void CheckThread(int flags) {
Elliott Hughesa2501992011-08-26 19:39:54 -0700725 Thread* self = Thread::Current();
726 if (self == NULL) {
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700727 JniAbortF(function_name_, "a thread (tid %d) is making JNI calls without being attached", GetTid());
Elliott Hughesa2501992011-08-26 19:39:54 -0700728 return;
729 }
730
731 // Get the *correct* JNIEnv by going through our TLS pointer.
732 JNIEnvExt* threadEnv = self->GetJniEnv();
733
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700734 // Verify that the current thread is (a) attached and (b) associated with
735 // this particular instance of JNIEnv.
Ian Rogers365c1022012-06-22 15:05:28 -0700736 if (ts_.Env() != threadEnv) {
737 if (ts_.Vm()->work_around_app_jni_bugs) {
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700738 // If we're keeping broken code limping along, we need to suppress the abort...
Ian Rogers365c1022012-06-22 15:05:28 -0700739 LOG(ERROR) << "APP BUG DETECTED: thread " << *self << " using JNIEnv* from thread " << *ts_.Self();
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700740 } else {
741 JniAbortF(function_name_, "thread %s using JNIEnv* from thread %s",
Ian Rogers365c1022012-06-22 15:05:28 -0700742 ToStr<Thread>(*self).c_str(), ToStr<Thread>(*ts_.Self()).c_str());
Elliott Hughesa2501992011-08-26 19:39:54 -0700743 return;
744 }
745 }
746
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700747 // Verify that, if this thread previously made a critical "get" call, we
748 // do the corresponding "release" call before we try anything else.
Elliott Hughesa2501992011-08-26 19:39:54 -0700749 switch (flags & kFlag_CritMask) {
750 case kFlag_CritOkay: // okay to call this method
751 break;
752 case kFlag_CritBad: // not okay to call
753 if (threadEnv->critical) {
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700754 JniAbortF(function_name_, "thread %s using JNI after critical get", ToStr<Thread>(*self).c_str());
Elliott Hughesa2501992011-08-26 19:39:54 -0700755 return;
756 }
757 break;
758 case kFlag_CritGet: // this is a "get" call
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700759 // Don't check here; we allow nested gets.
Elliott Hughesa2501992011-08-26 19:39:54 -0700760 threadEnv->critical++;
761 break;
762 case kFlag_CritRelease: // this is a "release" call
763 threadEnv->critical--;
764 if (threadEnv->critical < 0) {
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700765 JniAbortF(function_name_, "thread %s called too many critical releases", ToStr<Thread>(*self).c_str());
Elliott Hughesa2501992011-08-26 19:39:54 -0700766 return;
767 }
768 break;
769 default:
Elliott Hughes3d30d9b2011-12-07 17:35:48 -0800770 LOG(FATAL) << "Bad flags (internal error): " << flags;
Elliott Hughesa2501992011-08-26 19:39:54 -0700771 }
772
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700773 // Verify that, if an exception has been raised, the native code doesn't
774 // make any JNI calls other than the Exception* methods.
Elliott Hughesa2501992011-08-26 19:39:54 -0700775 if ((flags & kFlag_ExcepOkay) == 0 && self->IsExceptionPending()) {
Elliott Hughes30646832011-10-13 16:59:46 -0700776 std::string type(PrettyTypeOf(self->GetException()));
Elliott Hughes30646832011-10-13 16:59:46 -0700777 // TODO: write native code that doesn't require allocation for dumping an exception.
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700778 // TODO: do we care any more? art always dumps pending exceptions on aborting threads.
Elliott Hughes30646832011-10-13 16:59:46 -0700779 if (type != "java.lang.OutOfMemoryError") {
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700780 JniAbortF(function_name_, "JNI %s called with pending exception: %s",
Ian Rogers365c1022012-06-22 15:05:28 -0700781 function_name_, type.c_str(), jniGetStackTrace(ts_.Env()).c_str());
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700782 } else {
783 JniAbortF(function_name_, "JNI %s called with %s pending", function_name_, type.c_str());
Elliott Hughes30646832011-10-13 16:59:46 -0700784 }
Elliott Hughesa2501992011-08-26 19:39:54 -0700785 return;
786 }
787 }
788
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700789 // Verifies that "bytes" points to valid Modified UTF-8 data.
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700790 void CheckUtfString(const char* bytes, bool nullable) {
Elliott Hughesa2501992011-08-26 19:39:54 -0700791 if (bytes == NULL) {
792 if (!nullable) {
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700793 JniAbortF(function_name_, "non-nullable const char* was NULL");
Elliott Hughesa2501992011-08-26 19:39:54 -0700794 return;
795 }
796 return;
797 }
798
799 const char* errorKind = NULL;
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700800 uint8_t utf8 = CheckUtfBytes(bytes, &errorKind);
Elliott Hughesa2501992011-08-26 19:39:54 -0700801 if (errorKind != NULL) {
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700802 JniAbortF(function_name_,
803 "input is not valid Modified UTF-8: illegal %s byte %#x\n"
804 " string: '%s'", errorKind, utf8, bytes);
Elliott Hughesa2501992011-08-26 19:39:54 -0700805 return;
806 }
807 }
808
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700809 static uint8_t CheckUtfBytes(const char* bytes, const char** errorKind) {
Elliott Hughesa2501992011-08-26 19:39:54 -0700810 while (*bytes != '\0') {
811 uint8_t utf8 = *(bytes++);
812 // Switch on the high four bits.
813 switch (utf8 >> 4) {
814 case 0x00:
815 case 0x01:
816 case 0x02:
817 case 0x03:
818 case 0x04:
819 case 0x05:
820 case 0x06:
821 case 0x07:
822 // Bit pattern 0xxx. No need for any extra bytes.
823 break;
824 case 0x08:
825 case 0x09:
826 case 0x0a:
827 case 0x0b:
828 case 0x0f:
829 /*
830 * Bit pattern 10xx or 1111, which are illegal start bytes.
831 * Note: 1111 is valid for normal UTF-8, but not the
Elliott Hughes78090d12011-10-07 14:31:47 -0700832 * Modified UTF-8 used here.
Elliott Hughesa2501992011-08-26 19:39:54 -0700833 */
834 *errorKind = "start";
835 return utf8;
836 case 0x0e:
837 // Bit pattern 1110, so there are two additional bytes.
838 utf8 = *(bytes++);
839 if ((utf8 & 0xc0) != 0x80) {
840 *errorKind = "continuation";
841 return utf8;
842 }
843 // Fall through to take care of the final byte.
844 case 0x0c:
845 case 0x0d:
846 // Bit pattern 110x, so there is one additional byte.
847 utf8 = *(bytes++);
848 if ((utf8 & 0xc0) != 0x80) {
849 *errorKind = "continuation";
850 return utf8;
851 }
852 break;
853 }
854 }
855 return 0;
856 }
857
Ian Rogers365c1022012-06-22 15:05:28 -0700858 const ScopedJniThreadState ts_;
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700859 const char* function_name_;
860 int flags_;
861 bool has_method_;
Elliott Hughes92cb4982011-12-16 16:57:28 -0800862 int indent_;
Elliott Hughesa2501992011-08-26 19:39:54 -0700863
864 DISALLOW_COPY_AND_ASSIGN(ScopedCheck);
865};
866
867#define CHECK_JNI_ENTRY(flags, types, args...) \
868 ScopedCheck sc(env, flags, __FUNCTION__); \
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700869 sc.Check(true, types, ##args)
Elliott Hughesa2501992011-08-26 19:39:54 -0700870
871#define CHECK_JNI_EXIT(type, exp) ({ \
Elliott Hughes362f9bc2011-10-17 18:56:41 -0700872 typeof(exp) _rc = (exp); \
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700873 sc.Check(false, type, _rc); \
Elliott Hughesa2501992011-08-26 19:39:54 -0700874 _rc; })
875#define CHECK_JNI_EXIT_VOID() \
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700876 sc.Check(false, "V")
Elliott Hughesa2501992011-08-26 19:39:54 -0700877
878/*
879 * ===========================================================================
880 * Guarded arrays
881 * ===========================================================================
882 */
883
884#define kGuardLen 512 /* must be multiple of 2 */
885#define kGuardPattern 0xd5e3 /* uncommon values; d5e3d5e3 invalid addr */
886#define kGuardMagic 0xffd5aa96
887
888/* this gets tucked in at the start of the buffer; struct size must be even */
889struct GuardedCopy {
890 uint32_t magic;
891 uLong adler;
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700892 size_t original_length;
893 const void* original_ptr;
Elliott Hughesa2501992011-08-26 19:39:54 -0700894
895 /* find the GuardedCopy given the pointer into the "live" data */
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700896 static inline const GuardedCopy* FromData(const void* dataBuf) {
897 return reinterpret_cast<const GuardedCopy*>(ActualBuffer(dataBuf));
Elliott Hughesa2501992011-08-26 19:39:54 -0700898 }
899
900 /*
901 * Create an over-sized buffer to hold the contents of "buf". Copy it in,
902 * filling in the area around it with guard data.
903 *
904 * We use a 16-bit pattern to make a rogue memset less likely to elude us.
905 */
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700906 static void* Create(const void* buf, size_t len, bool modOkay) {
907 size_t newLen = ActualLength(len);
908 uint8_t* newBuf = DebugAlloc(newLen);
Elliott Hughesa2501992011-08-26 19:39:54 -0700909
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700910 // Fill it in with a pattern.
Elliott Hughesba8eee12012-01-24 20:25:24 -0800911 uint16_t* pat = reinterpret_cast<uint16_t*>(newBuf);
Elliott Hughesa2501992011-08-26 19:39:54 -0700912 for (size_t i = 0; i < newLen / 2; i++) {
913 *pat++ = kGuardPattern;
914 }
915
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700916 // Copy the data in; note "len" could be zero.
Elliott Hughesa2501992011-08-26 19:39:54 -0700917 memcpy(newBuf + kGuardLen / 2, buf, len);
918
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700919 // If modification is not expected, grab a checksum.
Elliott Hughesa2501992011-08-26 19:39:54 -0700920 uLong adler = 0;
921 if (!modOkay) {
922 adler = adler32(0L, Z_NULL, 0);
Elliott Hughesba8eee12012-01-24 20:25:24 -0800923 adler = adler32(adler, reinterpret_cast<const Bytef*>(buf), len);
924 *reinterpret_cast<uLong*>(newBuf) = adler;
Elliott Hughesa2501992011-08-26 19:39:54 -0700925 }
926
927 GuardedCopy* pExtra = reinterpret_cast<GuardedCopy*>(newBuf);
928 pExtra->magic = kGuardMagic;
929 pExtra->adler = adler;
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700930 pExtra->original_ptr = buf;
931 pExtra->original_length = len;
Elliott Hughesa2501992011-08-26 19:39:54 -0700932
933 return newBuf + kGuardLen / 2;
934 }
935
936 /*
937 * Free up the guard buffer, scrub it, and return the original pointer.
938 */
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700939 static void* Destroy(void* dataBuf) {
940 const GuardedCopy* pExtra = GuardedCopy::FromData(dataBuf);
Elliott Hughesba8eee12012-01-24 20:25:24 -0800941 void* original_ptr = const_cast<void*>(pExtra->original_ptr);
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700942 size_t len = pExtra->original_length;
943 DebugFree(dataBuf, len);
944 return original_ptr;
Elliott Hughesa2501992011-08-26 19:39:54 -0700945 }
946
947 /*
948 * Verify the guard area and, if "modOkay" is false, that the data itself
949 * has not been altered.
950 *
951 * The caller has already checked that "dataBuf" is non-NULL.
952 */
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700953 static void Check(const char* functionName, const void* dataBuf, bool modOkay) {
Elliott Hughesa2501992011-08-26 19:39:54 -0700954 static const uint32_t kMagicCmp = kGuardMagic;
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700955 const uint8_t* fullBuf = ActualBuffer(dataBuf);
956 const GuardedCopy* pExtra = GuardedCopy::FromData(dataBuf);
Elliott Hughesa2501992011-08-26 19:39:54 -0700957
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700958 // Before we do anything with "pExtra", check the magic number. We
959 // do the check with memcmp rather than "==" in case the pointer is
960 // unaligned. If it points to completely bogus memory we're going
961 // to crash, but there's no easy way around that.
Elliott Hughesa2501992011-08-26 19:39:54 -0700962 if (memcmp(&pExtra->magic, &kMagicCmp, 4) != 0) {
963 uint8_t buf[4];
964 memcpy(buf, &pExtra->magic, 4);
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700965 JniAbortF(functionName,
966 "guard magic does not match (found 0x%02x%02x%02x%02x) -- incorrect data pointer %p?",
967 buf[3], buf[2], buf[1], buf[0], dataBuf); // Assumes little-endian.
Elliott Hughesa2501992011-08-26 19:39:54 -0700968 }
969
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700970 size_t len = pExtra->original_length;
Elliott Hughesa2501992011-08-26 19:39:54 -0700971
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700972 // Check bottom half of guard; skip over optional checksum storage.
Elliott Hughesba8eee12012-01-24 20:25:24 -0800973 const uint16_t* pat = reinterpret_cast<const uint16_t*>(fullBuf);
Elliott Hughesa2501992011-08-26 19:39:54 -0700974 for (size_t i = sizeof(GuardedCopy) / 2; i < (kGuardLen / 2 - sizeof(GuardedCopy)) / 2; i++) {
975 if (pat[i] != kGuardPattern) {
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700976 JniAbortF(functionName, "guard pattern(1) disturbed at %p +%d", fullBuf, i*2);
Elliott Hughesa2501992011-08-26 19:39:54 -0700977 }
978 }
979
980 int offset = kGuardLen / 2 + len;
981 if (offset & 0x01) {
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700982 // Odd byte; expected value depends on endian.
Elliott Hughesa2501992011-08-26 19:39:54 -0700983 const uint16_t patSample = kGuardPattern;
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700984 uint8_t expected_byte = reinterpret_cast<const uint8_t*>(&patSample)[1];
985 if (fullBuf[offset] != expected_byte) {
986 JniAbortF(functionName, "guard pattern disturbed in odd byte after %p +%d 0x%02x 0x%02x",
987 fullBuf, offset, fullBuf[offset], expected_byte);
Elliott Hughesa2501992011-08-26 19:39:54 -0700988 }
989 offset++;
990 }
991
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700992 // Check top half of guard.
Elliott Hughesba8eee12012-01-24 20:25:24 -0800993 pat = reinterpret_cast<const uint16_t*>(fullBuf + offset);
Elliott Hughesa2501992011-08-26 19:39:54 -0700994 for (size_t i = 0; i < kGuardLen / 4; i++) {
995 if (pat[i] != kGuardPattern) {
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700996 JniAbortF(functionName, "guard pattern(2) disturbed at %p +%d", fullBuf, offset + i*2);
Elliott Hughesa2501992011-08-26 19:39:54 -0700997 }
998 }
999
Elliott Hughes3f6635a2012-06-19 13:37:49 -07001000 // If modification is not expected, verify checksum. Strictly speaking
1001 // this is wrong: if we told the client that we made a copy, there's no
1002 // reason they can't alter the buffer.
Elliott Hughesa2501992011-08-26 19:39:54 -07001003 if (!modOkay) {
1004 uLong adler = adler32(0L, Z_NULL, 0);
1005 adler = adler32(adler, (const Bytef*)dataBuf, len);
1006 if (pExtra->adler != adler) {
Elliott Hughes3f6635a2012-06-19 13:37:49 -07001007 JniAbortF(functionName, "buffer modified (0x%08lx vs 0x%08lx) at address %p",
1008 pExtra->adler, adler, dataBuf);
Elliott Hughesa2501992011-08-26 19:39:54 -07001009 }
1010 }
1011 }
1012
1013 private:
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001014 static uint8_t* DebugAlloc(size_t len) {
Elliott Hughesa2501992011-08-26 19:39:54 -07001015 void* result = mmap(NULL, len, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON, -1, 0);
1016 if (result == MAP_FAILED) {
1017 PLOG(FATAL) << "GuardedCopy::create mmap(" << len << ") failed";
1018 }
1019 return reinterpret_cast<uint8_t*>(result);
1020 }
1021
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001022 static void DebugFree(void* dataBuf, size_t len) {
1023 uint8_t* fullBuf = ActualBuffer(dataBuf);
1024 size_t totalByteCount = ActualLength(len);
Elliott Hughesa2501992011-08-26 19:39:54 -07001025 // TODO: we could mprotect instead, and keep the allocation around for a while.
1026 // This would be even more expensive, but it might catch more errors.
1027 // if (mprotect(fullBuf, totalByteCount, PROT_NONE) != 0) {
Elliott Hughes7b9d9962012-04-20 18:48:18 -07001028 // PLOG(WARNING) << "mprotect(PROT_NONE) failed";
Elliott Hughesa2501992011-08-26 19:39:54 -07001029 // }
1030 if (munmap(fullBuf, totalByteCount) != 0) {
Elliott Hughesba8eee12012-01-24 20:25:24 -08001031 PLOG(FATAL) << "munmap(" << reinterpret_cast<void*>(fullBuf) << ", " << totalByteCount << ") failed";
Elliott Hughesa2501992011-08-26 19:39:54 -07001032 }
1033 }
1034
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001035 static const uint8_t* ActualBuffer(const void* dataBuf) {
Elliott Hughesa2501992011-08-26 19:39:54 -07001036 return reinterpret_cast<const uint8_t*>(dataBuf) - kGuardLen / 2;
1037 }
1038
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001039 static uint8_t* ActualBuffer(void* dataBuf) {
Elliott Hughesa2501992011-08-26 19:39:54 -07001040 return reinterpret_cast<uint8_t*>(dataBuf) - kGuardLen / 2;
1041 }
1042
1043 // Underlying length of a user allocation of 'length' bytes.
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001044 static size_t ActualLength(size_t length) {
Elliott Hughesa2501992011-08-26 19:39:54 -07001045 return (length + kGuardLen + 1) & ~0x01;
1046 }
1047};
1048
1049/*
1050 * Create a guarded copy of a primitive array. Modifications to the copied
1051 * data are allowed. Returns a pointer to the copied data.
1052 */
Elliott Hughes3f6635a2012-06-19 13:37:49 -07001053static void* CreateGuardedPACopy(JNIEnv* env, const jarray java_array, jboolean* isCopy) {
Elliott Hughesa2501992011-08-26 19:39:54 -07001054 ScopedJniThreadState ts(env);
1055
Ian Rogers365c1022012-06-22 15:05:28 -07001056 Array* a = ts.Decode<Array*>(java_array);
Ian Rogersa15e67d2012-02-28 13:51:55 -08001057 size_t component_size = a->GetClass()->GetComponentSize();
1058 size_t byte_count = a->GetLength() * component_size;
1059 void* result = GuardedCopy::Create(a->GetRawData(component_size), byte_count, true);
Elliott Hughesa2501992011-08-26 19:39:54 -07001060 if (isCopy != NULL) {
1061 *isCopy = JNI_TRUE;
1062 }
1063 return result;
1064}
1065
1066/*
1067 * Perform the array "release" operation, which may or may not copy data
Elliott Hughes81ff3182012-03-23 20:35:56 -07001068 * back into the managed heap, and may or may not release the underlying storage.
Elliott Hughesa2501992011-08-26 19:39:54 -07001069 */
Elliott Hughes3f6635a2012-06-19 13:37:49 -07001070static void ReleaseGuardedPACopy(JNIEnv* env, jarray java_array, void* dataBuf, int mode) {
Elliott Hughesa2501992011-08-26 19:39:54 -07001071 if (reinterpret_cast<uintptr_t>(dataBuf) == kNoCopyMagic) {
1072 return;
1073 }
1074
1075 ScopedJniThreadState ts(env);
Ian Rogers365c1022012-06-22 15:05:28 -07001076 Array* a = ts.Decode<Array*>(java_array);
Elliott Hughesa2501992011-08-26 19:39:54 -07001077
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001078 GuardedCopy::Check(__FUNCTION__, dataBuf, true);
Elliott Hughesa2501992011-08-26 19:39:54 -07001079
1080 if (mode != JNI_ABORT) {
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001081 size_t len = GuardedCopy::FromData(dataBuf)->original_length;
Ian Rogersa15e67d2012-02-28 13:51:55 -08001082 memcpy(a->GetRawData(a->GetClass()->GetComponentSize()), dataBuf, len);
Elliott Hughesa2501992011-08-26 19:39:54 -07001083 }
1084 if (mode != JNI_COMMIT) {
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001085 GuardedCopy::Destroy(dataBuf);
Elliott Hughesa2501992011-08-26 19:39:54 -07001086 }
1087}
1088
1089/*
1090 * ===========================================================================
1091 * JNI functions
1092 * ===========================================================================
1093 */
1094
1095class CheckJNI {
1096 public:
1097 static jint GetVersion(JNIEnv* env) {
1098 CHECK_JNI_ENTRY(kFlag_Default, "E", env);
1099 return CHECK_JNI_EXIT("I", baseEnv(env)->GetVersion(env));
1100 }
1101
1102 static jclass DefineClass(JNIEnv* env, const char* name, jobject loader, const jbyte* buf, jsize bufLen) {
1103 CHECK_JNI_ENTRY(kFlag_Default, "EuLpz", env, name, loader, buf, bufLen);
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001104 sc.CheckClassName(name);
Elliott Hughesa2501992011-08-26 19:39:54 -07001105 return CHECK_JNI_EXIT("c", baseEnv(env)->DefineClass(env, name, loader, buf, bufLen));
1106 }
1107
1108 static jclass FindClass(JNIEnv* env, const char* name) {
1109 CHECK_JNI_ENTRY(kFlag_Default, "Eu", env, name);
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001110 sc.CheckClassName(name);
Elliott Hughesa2501992011-08-26 19:39:54 -07001111 return CHECK_JNI_EXIT("c", baseEnv(env)->FindClass(env, name));
1112 }
1113
Elliott Hughese84278b2012-03-22 10:06:53 -07001114 static jclass GetSuperclass(JNIEnv* env, jclass c) {
1115 CHECK_JNI_ENTRY(kFlag_Default, "Ec", env, c);
1116 return CHECK_JNI_EXIT("c", baseEnv(env)->GetSuperclass(env, c));
Elliott Hughesa2501992011-08-26 19:39:54 -07001117 }
1118
Elliott Hughese84278b2012-03-22 10:06:53 -07001119 static jboolean IsAssignableFrom(JNIEnv* env, jclass c1, jclass c2) {
1120 CHECK_JNI_ENTRY(kFlag_Default, "Ecc", env, c1, c2);
1121 return CHECK_JNI_EXIT("b", baseEnv(env)->IsAssignableFrom(env, c1, c2));
Elliott Hughesa2501992011-08-26 19:39:54 -07001122 }
1123
1124 static jmethodID FromReflectedMethod(JNIEnv* env, jobject method) {
1125 CHECK_JNI_ENTRY(kFlag_Default, "EL", env, method);
1126 // TODO: check that 'field' is a java.lang.reflect.Method.
1127 return CHECK_JNI_EXIT("m", baseEnv(env)->FromReflectedMethod(env, method));
1128 }
1129
1130 static jfieldID FromReflectedField(JNIEnv* env, jobject field) {
1131 CHECK_JNI_ENTRY(kFlag_Default, "EL", env, field);
1132 // TODO: check that 'field' is a java.lang.reflect.Field.
1133 return CHECK_JNI_EXIT("f", baseEnv(env)->FromReflectedField(env, field));
1134 }
1135
1136 static jobject ToReflectedMethod(JNIEnv* env, jclass cls, jmethodID mid, jboolean isStatic) {
1137 CHECK_JNI_ENTRY(kFlag_Default, "Ecmb", env, cls, mid, isStatic);
1138 return CHECK_JNI_EXIT("L", baseEnv(env)->ToReflectedMethod(env, cls, mid, isStatic));
1139 }
1140
1141 static jobject ToReflectedField(JNIEnv* env, jclass cls, jfieldID fid, jboolean isStatic) {
1142 CHECK_JNI_ENTRY(kFlag_Default, "Ecfb", env, cls, fid, isStatic);
1143 return CHECK_JNI_EXIT("L", baseEnv(env)->ToReflectedField(env, cls, fid, isStatic));
1144 }
1145
1146 static jint Throw(JNIEnv* env, jthrowable obj) {
1147 CHECK_JNI_ENTRY(kFlag_Default, "EL", env, obj);
1148 // TODO: check that 'obj' is a java.lang.Throwable.
1149 return CHECK_JNI_EXIT("I", baseEnv(env)->Throw(env, obj));
1150 }
1151
Elliott Hughese84278b2012-03-22 10:06:53 -07001152 static jint ThrowNew(JNIEnv* env, jclass c, const char* message) {
1153 CHECK_JNI_ENTRY(kFlag_NullableUtf, "Ecu", env, c, message);
1154 return CHECK_JNI_EXIT("I", baseEnv(env)->ThrowNew(env, c, message));
Elliott Hughesa2501992011-08-26 19:39:54 -07001155 }
1156
1157 static jthrowable ExceptionOccurred(JNIEnv* env) {
1158 CHECK_JNI_ENTRY(kFlag_ExcepOkay, "E", env);
1159 return CHECK_JNI_EXIT("L", baseEnv(env)->ExceptionOccurred(env));
1160 }
1161
1162 static void ExceptionDescribe(JNIEnv* env) {
1163 CHECK_JNI_ENTRY(kFlag_ExcepOkay, "E", env);
1164 baseEnv(env)->ExceptionDescribe(env);
1165 CHECK_JNI_EXIT_VOID();
1166 }
1167
1168 static void ExceptionClear(JNIEnv* env) {
1169 CHECK_JNI_ENTRY(kFlag_ExcepOkay, "E", env);
1170 baseEnv(env)->ExceptionClear(env);
1171 CHECK_JNI_EXIT_VOID();
1172 }
1173
1174 static void FatalError(JNIEnv* env, const char* msg) {
1175 CHECK_JNI_ENTRY(kFlag_NullableUtf, "Eu", env, msg);
1176 baseEnv(env)->FatalError(env, msg);
1177 CHECK_JNI_EXIT_VOID();
1178 }
1179
1180 static jint PushLocalFrame(JNIEnv* env, jint capacity) {
1181 CHECK_JNI_ENTRY(kFlag_Default | kFlag_ExcepOkay, "EI", env, capacity);
1182 return CHECK_JNI_EXIT("I", baseEnv(env)->PushLocalFrame(env, capacity));
1183 }
1184
1185 static jobject PopLocalFrame(JNIEnv* env, jobject res) {
1186 CHECK_JNI_ENTRY(kFlag_Default | kFlag_ExcepOkay, "EL", env, res);
1187 return CHECK_JNI_EXIT("L", baseEnv(env)->PopLocalFrame(env, res));
1188 }
1189
1190 static jobject NewGlobalRef(JNIEnv* env, jobject obj) {
1191 CHECK_JNI_ENTRY(kFlag_Default, "EL", env, obj);
1192 return CHECK_JNI_EXIT("L", baseEnv(env)->NewGlobalRef(env, obj));
1193 }
1194
1195 static jobject NewLocalRef(JNIEnv* env, jobject ref) {
1196 CHECK_JNI_ENTRY(kFlag_Default, "EL", env, ref);
1197 return CHECK_JNI_EXIT("L", baseEnv(env)->NewLocalRef(env, ref));
1198 }
1199
1200 static void DeleteGlobalRef(JNIEnv* env, jobject globalRef) {
1201 CHECK_JNI_ENTRY(kFlag_Default | kFlag_ExcepOkay, "EL", env, globalRef);
1202 if (globalRef != NULL && GetIndirectRefKind(globalRef) != kGlobal) {
Elliott Hughes3f6635a2012-06-19 13:37:49 -07001203 JniAbortF(__FUNCTION__, "DeleteGlobalRef on %s: %p",
1204 ToStr<IndirectRefKind>(GetIndirectRefKind(globalRef)).c_str(), globalRef);
Elliott Hughesa2501992011-08-26 19:39:54 -07001205 } else {
1206 baseEnv(env)->DeleteGlobalRef(env, globalRef);
1207 CHECK_JNI_EXIT_VOID();
1208 }
1209 }
1210
1211 static void DeleteWeakGlobalRef(JNIEnv* env, jweak weakGlobalRef) {
1212 CHECK_JNI_ENTRY(kFlag_Default | kFlag_ExcepOkay, "EL", env, weakGlobalRef);
1213 if (weakGlobalRef != NULL && GetIndirectRefKind(weakGlobalRef) != kWeakGlobal) {
Elliott Hughes3f6635a2012-06-19 13:37:49 -07001214 JniAbortF(__FUNCTION__, "DeleteWeakGlobalRef on %s: %p",
1215 ToStr<IndirectRefKind>(GetIndirectRefKind(weakGlobalRef)).c_str(), weakGlobalRef);
Elliott Hughesa2501992011-08-26 19:39:54 -07001216 } else {
1217 baseEnv(env)->DeleteWeakGlobalRef(env, weakGlobalRef);
1218 CHECK_JNI_EXIT_VOID();
1219 }
1220 }
1221
1222 static void DeleteLocalRef(JNIEnv* env, jobject localRef) {
1223 CHECK_JNI_ENTRY(kFlag_Default | kFlag_ExcepOkay, "EL", env, localRef);
Ian Rogers959f8ed2012-02-07 16:33:37 -08001224 if (localRef != NULL && GetIndirectRefKind(localRef) != kLocal && !IsSirtLocalRef(env, localRef)) {
Elliott Hughes3f6635a2012-06-19 13:37:49 -07001225 JniAbortF(__FUNCTION__, "DeleteLocalRef on %s: %p",
1226 ToStr<IndirectRefKind>(GetIndirectRefKind(localRef)).c_str(), localRef);
Elliott Hughesa2501992011-08-26 19:39:54 -07001227 } else {
1228 baseEnv(env)->DeleteLocalRef(env, localRef);
1229 CHECK_JNI_EXIT_VOID();
1230 }
1231 }
1232
1233 static jint EnsureLocalCapacity(JNIEnv *env, jint capacity) {
1234 CHECK_JNI_ENTRY(kFlag_Default, "EI", env, capacity);
1235 return CHECK_JNI_EXIT("I", baseEnv(env)->EnsureLocalCapacity(env, capacity));
1236 }
1237
1238 static jboolean IsSameObject(JNIEnv* env, jobject ref1, jobject ref2) {
1239 CHECK_JNI_ENTRY(kFlag_Default, "ELL", env, ref1, ref2);
1240 return CHECK_JNI_EXIT("b", baseEnv(env)->IsSameObject(env, ref1, ref2));
1241 }
1242
Elliott Hughese84278b2012-03-22 10:06:53 -07001243 static jobject AllocObject(JNIEnv* env, jclass c) {
1244 CHECK_JNI_ENTRY(kFlag_Default, "Ec", env, c);
1245 return CHECK_JNI_EXIT("L", baseEnv(env)->AllocObject(env, c));
Elliott Hughesa2501992011-08-26 19:39:54 -07001246 }
1247
Elliott Hughese84278b2012-03-22 10:06:53 -07001248 static jobject NewObject(JNIEnv* env, jclass c, jmethodID mid, ...) {
1249 CHECK_JNI_ENTRY(kFlag_Default, "Ecm.", env, c, mid);
Elliott Hughesa2501992011-08-26 19:39:54 -07001250 va_list args;
1251 va_start(args, mid);
Elliott Hughese84278b2012-03-22 10:06:53 -07001252 jobject result = baseEnv(env)->NewObjectV(env, c, mid, args);
Elliott Hughesa2501992011-08-26 19:39:54 -07001253 va_end(args);
1254 return CHECK_JNI_EXIT("L", result);
1255 }
1256
Elliott Hughese84278b2012-03-22 10:06:53 -07001257 static jobject NewObjectV(JNIEnv* env, jclass c, jmethodID mid, va_list args) {
1258 CHECK_JNI_ENTRY(kFlag_Default, "Ecm.", env, c, mid);
1259 return CHECK_JNI_EXIT("L", baseEnv(env)->NewObjectV(env, c, mid, args));
Elliott Hughesa2501992011-08-26 19:39:54 -07001260 }
1261
Elliott Hughese84278b2012-03-22 10:06:53 -07001262 static jobject NewObjectA(JNIEnv* env, jclass c, jmethodID mid, jvalue* args) {
1263 CHECK_JNI_ENTRY(kFlag_Default, "Ecm.", env, c, mid);
1264 return CHECK_JNI_EXIT("L", baseEnv(env)->NewObjectA(env, c, mid, args));
Elliott Hughesa2501992011-08-26 19:39:54 -07001265 }
1266
1267 static jclass GetObjectClass(JNIEnv* env, jobject obj) {
1268 CHECK_JNI_ENTRY(kFlag_Default, "EL", env, obj);
1269 return CHECK_JNI_EXIT("c", baseEnv(env)->GetObjectClass(env, obj));
1270 }
1271
Elliott Hughese84278b2012-03-22 10:06:53 -07001272 static jboolean IsInstanceOf(JNIEnv* env, jobject obj, jclass c) {
1273 CHECK_JNI_ENTRY(kFlag_Default, "ELc", env, obj, c);
1274 return CHECK_JNI_EXIT("b", baseEnv(env)->IsInstanceOf(env, obj, c));
Elliott Hughesa2501992011-08-26 19:39:54 -07001275 }
1276
Elliott Hughese84278b2012-03-22 10:06:53 -07001277 static jmethodID GetMethodID(JNIEnv* env, jclass c, const char* name, const char* sig) {
1278 CHECK_JNI_ENTRY(kFlag_Default, "Ecuu", env, c, name, sig);
1279 return CHECK_JNI_EXIT("m", baseEnv(env)->GetMethodID(env, c, name, sig));
Elliott Hughesa2501992011-08-26 19:39:54 -07001280 }
1281
Elliott Hughese84278b2012-03-22 10:06:53 -07001282 static jfieldID GetFieldID(JNIEnv* env, jclass c, const char* name, const char* sig) {
1283 CHECK_JNI_ENTRY(kFlag_Default, "Ecuu", env, c, name, sig);
1284 return CHECK_JNI_EXIT("f", baseEnv(env)->GetFieldID(env, c, name, sig));
Elliott Hughesa2501992011-08-26 19:39:54 -07001285 }
1286
Elliott Hughese84278b2012-03-22 10:06:53 -07001287 static jmethodID GetStaticMethodID(JNIEnv* env, jclass c, const char* name, const char* sig) {
1288 CHECK_JNI_ENTRY(kFlag_Default, "Ecuu", env, c, name, sig);
1289 return CHECK_JNI_EXIT("m", baseEnv(env)->GetStaticMethodID(env, c, name, sig));
Elliott Hughesa2501992011-08-26 19:39:54 -07001290 }
1291
Elliott Hughese84278b2012-03-22 10:06:53 -07001292 static jfieldID GetStaticFieldID(JNIEnv* env, jclass c, const char* name, const char* sig) {
1293 CHECK_JNI_ENTRY(kFlag_Default, "Ecuu", env, c, name, sig);
1294 return CHECK_JNI_EXIT("f", baseEnv(env)->GetStaticFieldID(env, c, name, sig));
Elliott Hughesa2501992011-08-26 19:39:54 -07001295 }
1296
1297#define FIELD_ACCESSORS(_ctype, _jname, _type) \
Elliott Hughese84278b2012-03-22 10:06:53 -07001298 static _ctype GetStatic##_jname##Field(JNIEnv* env, jclass c, jfieldID fid) { \
1299 CHECK_JNI_ENTRY(kFlag_Default, "Ecf", env, c, fid); \
1300 sc.CheckStaticFieldID(c, fid); \
1301 return CHECK_JNI_EXIT(_type, baseEnv(env)->GetStatic##_jname##Field(env, c, fid)); \
Elliott Hughesa2501992011-08-26 19:39:54 -07001302 } \
1303 static _ctype Get##_jname##Field(JNIEnv* env, jobject obj, jfieldID fid) { \
1304 CHECK_JNI_ENTRY(kFlag_Default, "ELf", env, obj, fid); \
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001305 sc.CheckInstanceFieldID(obj, fid); \
Elliott Hughesa2501992011-08-26 19:39:54 -07001306 return CHECK_JNI_EXIT(_type, baseEnv(env)->Get##_jname##Field(env, obj, fid)); \
1307 } \
Elliott Hughese84278b2012-03-22 10:06:53 -07001308 static void SetStatic##_jname##Field(JNIEnv* env, jclass c, jfieldID fid, _ctype value) { \
1309 CHECK_JNI_ENTRY(kFlag_Default, "Ecf" _type, env, c, fid, value); \
1310 sc.CheckStaticFieldID(c, fid); \
Elliott Hughesa2501992011-08-26 19:39:54 -07001311 /* "value" arg only used when type == ref */ \
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001312 sc.CheckFieldType((jobject)(uint32_t)value, fid, _type[0], true); \
Elliott Hughese84278b2012-03-22 10:06:53 -07001313 baseEnv(env)->SetStatic##_jname##Field(env, c, fid, value); \
Elliott Hughesa2501992011-08-26 19:39:54 -07001314 CHECK_JNI_EXIT_VOID(); \
1315 } \
1316 static void Set##_jname##Field(JNIEnv* env, jobject obj, jfieldID fid, _ctype value) { \
1317 CHECK_JNI_ENTRY(kFlag_Default, "ELf" _type, env, obj, fid, value); \
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001318 sc.CheckInstanceFieldID(obj, fid); \
Elliott Hughesa2501992011-08-26 19:39:54 -07001319 /* "value" arg only used when type == ref */ \
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001320 sc.CheckFieldType((jobject)(uint32_t) value, fid, _type[0], false); \
Elliott Hughesa2501992011-08-26 19:39:54 -07001321 baseEnv(env)->Set##_jname##Field(env, obj, fid, value); \
1322 CHECK_JNI_EXIT_VOID(); \
1323 }
1324
1325FIELD_ACCESSORS(jobject, Object, "L");
1326FIELD_ACCESSORS(jboolean, Boolean, "Z");
1327FIELD_ACCESSORS(jbyte, Byte, "B");
1328FIELD_ACCESSORS(jchar, Char, "C");
1329FIELD_ACCESSORS(jshort, Short, "S");
1330FIELD_ACCESSORS(jint, Int, "I");
1331FIELD_ACCESSORS(jlong, Long, "J");
1332FIELD_ACCESSORS(jfloat, Float, "F");
1333FIELD_ACCESSORS(jdouble, Double, "D");
1334
1335#define CALL(_ctype, _jname, _retdecl, _retasgn, _retok, _retsig) \
1336 /* Virtual... */ \
1337 static _ctype Call##_jname##Method(JNIEnv* env, jobject obj, \
1338 jmethodID mid, ...) \
1339 { \
1340 CHECK_JNI_ENTRY(kFlag_Default, "ELm.", env, obj, mid); /* TODO: args! */ \
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001341 sc.CheckSig(mid, _retsig, false); \
1342 sc.CheckVirtualMethod(obj, mid); \
Elliott Hughesa2501992011-08-26 19:39:54 -07001343 _retdecl; \
1344 va_list args; \
1345 va_start(args, mid); \
Elliott Hughesba8eee12012-01-24 20:25:24 -08001346 _retasgn(baseEnv(env)->Call##_jname##MethodV(env, obj, mid, args)); \
Elliott Hughesa2501992011-08-26 19:39:54 -07001347 va_end(args); \
1348 _retok; \
1349 } \
1350 static _ctype Call##_jname##MethodV(JNIEnv* env, jobject obj, \
1351 jmethodID mid, va_list args) \
1352 { \
1353 CHECK_JNI_ENTRY(kFlag_Default, "ELm.", env, obj, mid); /* TODO: args! */ \
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001354 sc.CheckSig(mid, _retsig, false); \
1355 sc.CheckVirtualMethod(obj, mid); \
Elliott Hughesa2501992011-08-26 19:39:54 -07001356 _retdecl; \
Elliott Hughesba8eee12012-01-24 20:25:24 -08001357 _retasgn(baseEnv(env)->Call##_jname##MethodV(env, obj, mid, args)); \
Elliott Hughesa2501992011-08-26 19:39:54 -07001358 _retok; \
1359 } \
1360 static _ctype Call##_jname##MethodA(JNIEnv* env, jobject obj, \
1361 jmethodID mid, jvalue* args) \
1362 { \
1363 CHECK_JNI_ENTRY(kFlag_Default, "ELm.", env, obj, mid); /* TODO: args! */ \
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001364 sc.CheckSig(mid, _retsig, false); \
1365 sc.CheckVirtualMethod(obj, mid); \
Elliott Hughesa2501992011-08-26 19:39:54 -07001366 _retdecl; \
Elliott Hughesba8eee12012-01-24 20:25:24 -08001367 _retasgn(baseEnv(env)->Call##_jname##MethodA(env, obj, mid, args)); \
Elliott Hughesa2501992011-08-26 19:39:54 -07001368 _retok; \
1369 } \
1370 /* Non-virtual... */ \
1371 static _ctype CallNonvirtual##_jname##Method(JNIEnv* env, \
Elliott Hughese84278b2012-03-22 10:06:53 -07001372 jobject obj, jclass c, jmethodID mid, ...) \
Elliott Hughesa2501992011-08-26 19:39:54 -07001373 { \
Elliott Hughese84278b2012-03-22 10:06:53 -07001374 CHECK_JNI_ENTRY(kFlag_Default, "ELcm.", env, obj, c, mid); /* TODO: args! */ \
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001375 sc.CheckSig(mid, _retsig, false); \
1376 sc.CheckVirtualMethod(obj, mid); \
Elliott Hughesa2501992011-08-26 19:39:54 -07001377 _retdecl; \
1378 va_list args; \
1379 va_start(args, mid); \
Elliott Hughese84278b2012-03-22 10:06:53 -07001380 _retasgn(baseEnv(env)->CallNonvirtual##_jname##MethodV(env, obj, c, mid, args)); \
Elliott Hughesa2501992011-08-26 19:39:54 -07001381 va_end(args); \
1382 _retok; \
1383 } \
1384 static _ctype CallNonvirtual##_jname##MethodV(JNIEnv* env, \
Elliott Hughese84278b2012-03-22 10:06:53 -07001385 jobject obj, jclass c, jmethodID mid, va_list args) \
Elliott Hughesa2501992011-08-26 19:39:54 -07001386 { \
Elliott Hughese84278b2012-03-22 10:06:53 -07001387 CHECK_JNI_ENTRY(kFlag_Default, "ELcm.", env, obj, c, mid); /* TODO: args! */ \
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001388 sc.CheckSig(mid, _retsig, false); \
1389 sc.CheckVirtualMethod(obj, mid); \
Elliott Hughesa2501992011-08-26 19:39:54 -07001390 _retdecl; \
Elliott Hughese84278b2012-03-22 10:06:53 -07001391 _retasgn(baseEnv(env)->CallNonvirtual##_jname##MethodV(env, obj, c, mid, args)); \
Elliott Hughesa2501992011-08-26 19:39:54 -07001392 _retok; \
1393 } \
1394 static _ctype CallNonvirtual##_jname##MethodA(JNIEnv* env, \
Elliott Hughese84278b2012-03-22 10:06:53 -07001395 jobject obj, jclass c, jmethodID mid, jvalue* args) \
Elliott Hughesa2501992011-08-26 19:39:54 -07001396 { \
Elliott Hughese84278b2012-03-22 10:06:53 -07001397 CHECK_JNI_ENTRY(kFlag_Default, "ELcm.", env, obj, c, mid); /* TODO: args! */ \
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001398 sc.CheckSig(mid, _retsig, false); \
1399 sc.CheckVirtualMethod(obj, mid); \
Elliott Hughesa2501992011-08-26 19:39:54 -07001400 _retdecl; \
Elliott Hughese84278b2012-03-22 10:06:53 -07001401 _retasgn(baseEnv(env)->CallNonvirtual##_jname##MethodA(env, obj, c, mid, args)); \
Elliott Hughesa2501992011-08-26 19:39:54 -07001402 _retok; \
1403 } \
1404 /* Static... */ \
Elliott Hughese84278b2012-03-22 10:06:53 -07001405 static _ctype CallStatic##_jname##Method(JNIEnv* env, jclass c, jmethodID mid, ...) \
Elliott Hughesa2501992011-08-26 19:39:54 -07001406 { \
Elliott Hughese84278b2012-03-22 10:06:53 -07001407 CHECK_JNI_ENTRY(kFlag_Default, "Ecm.", env, c, mid); /* TODO: args! */ \
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001408 sc.CheckSig(mid, _retsig, true); \
Elliott Hughese84278b2012-03-22 10:06:53 -07001409 sc.CheckStaticMethod(c, mid); \
Elliott Hughesa2501992011-08-26 19:39:54 -07001410 _retdecl; \
1411 va_list args; \
1412 va_start(args, mid); \
Elliott Hughese84278b2012-03-22 10:06:53 -07001413 _retasgn(baseEnv(env)->CallStatic##_jname##MethodV(env, c, mid, args)); \
Elliott Hughesa2501992011-08-26 19:39:54 -07001414 va_end(args); \
1415 _retok; \
1416 } \
Elliott Hughese84278b2012-03-22 10:06:53 -07001417 static _ctype CallStatic##_jname##MethodV(JNIEnv* env, jclass c, jmethodID mid, va_list args) \
Elliott Hughesa2501992011-08-26 19:39:54 -07001418 { \
Elliott Hughese84278b2012-03-22 10:06:53 -07001419 CHECK_JNI_ENTRY(kFlag_Default, "Ecm.", env, c, mid); /* TODO: args! */ \
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001420 sc.CheckSig(mid, _retsig, true); \
Elliott Hughese84278b2012-03-22 10:06:53 -07001421 sc.CheckStaticMethod(c, mid); \
Elliott Hughesa2501992011-08-26 19:39:54 -07001422 _retdecl; \
Elliott Hughese84278b2012-03-22 10:06:53 -07001423 _retasgn(baseEnv(env)->CallStatic##_jname##MethodV(env, c, mid, args)); \
Elliott Hughesa2501992011-08-26 19:39:54 -07001424 _retok; \
1425 } \
Elliott Hughese84278b2012-03-22 10:06:53 -07001426 static _ctype CallStatic##_jname##MethodA(JNIEnv* env, jclass c, jmethodID mid, jvalue* args) \
Elliott Hughesa2501992011-08-26 19:39:54 -07001427 { \
Elliott Hughese84278b2012-03-22 10:06:53 -07001428 CHECK_JNI_ENTRY(kFlag_Default, "Ecm.", env, c, mid); /* TODO: args! */ \
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001429 sc.CheckSig(mid, _retsig, true); \
Elliott Hughese84278b2012-03-22 10:06:53 -07001430 sc.CheckStaticMethod(c, mid); \
Elliott Hughesa2501992011-08-26 19:39:54 -07001431 _retdecl; \
Elliott Hughese84278b2012-03-22 10:06:53 -07001432 _retasgn(baseEnv(env)->CallStatic##_jname##MethodA(env, c, mid, args)); \
Elliott Hughesa2501992011-08-26 19:39:54 -07001433 _retok; \
1434 }
1435
1436#define NON_VOID_RETURN(_retsig, _ctype) return CHECK_JNI_EXIT(_retsig, (_ctype) result)
1437#define VOID_RETURN CHECK_JNI_EXIT_VOID()
1438
Elliott Hughesba8eee12012-01-24 20:25:24 -08001439CALL(jobject, Object, Object* result, result = reinterpret_cast<Object*>, NON_VOID_RETURN("L", jobject), "L");
1440CALL(jboolean, Boolean, jboolean result, result =, NON_VOID_RETURN("Z", jboolean), "Z");
1441CALL(jbyte, Byte, jbyte result, result =, NON_VOID_RETURN("B", jbyte), "B");
1442CALL(jchar, Char, jchar result, result =, NON_VOID_RETURN("C", jchar), "C");
1443CALL(jshort, Short, jshort result, result =, NON_VOID_RETURN("S", jshort), "S");
1444CALL(jint, Int, jint result, result =, NON_VOID_RETURN("I", jint), "I");
1445CALL(jlong, Long, jlong result, result =, NON_VOID_RETURN("J", jlong), "J");
1446CALL(jfloat, Float, jfloat result, result =, NON_VOID_RETURN("F", jfloat), "F");
1447CALL(jdouble, Double, jdouble result, result =, NON_VOID_RETURN("D", jdouble), "D");
Elliott Hughesa2501992011-08-26 19:39:54 -07001448CALL(void, Void, , , VOID_RETURN, "V");
1449
1450 static jstring NewString(JNIEnv* env, const jchar* unicodeChars, jsize len) {
1451 CHECK_JNI_ENTRY(kFlag_Default, "Epz", env, unicodeChars, len);
1452 return CHECK_JNI_EXIT("s", baseEnv(env)->NewString(env, unicodeChars, len));
1453 }
1454
1455 static jsize GetStringLength(JNIEnv* env, jstring string) {
1456 CHECK_JNI_ENTRY(kFlag_CritOkay, "Es", env, string);
1457 return CHECK_JNI_EXIT("I", baseEnv(env)->GetStringLength(env, string));
1458 }
1459
1460 static const jchar* GetStringChars(JNIEnv* env, jstring java_string, jboolean* isCopy) {
1461 CHECK_JNI_ENTRY(kFlag_CritOkay, "Esp", env, java_string, isCopy);
1462 const jchar* result = baseEnv(env)->GetStringChars(env, java_string, isCopy);
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001463 if (sc.ForceCopy() && result != NULL) {
Elliott Hughesa2501992011-08-26 19:39:54 -07001464 ScopedJniThreadState ts(env);
Ian Rogers365c1022012-06-22 15:05:28 -07001465 String* s = ts.Decode<String*>(java_string);
Elliott Hughesa2501992011-08-26 19:39:54 -07001466 int byteCount = s->GetLength() * 2;
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001467 result = (const jchar*) GuardedCopy::Create(result, byteCount, false);
Elliott Hughesa2501992011-08-26 19:39:54 -07001468 if (isCopy != NULL) {
1469 *isCopy = JNI_TRUE;
1470 }
1471 }
1472 return CHECK_JNI_EXIT("p", result);
1473 }
1474
1475 static void ReleaseStringChars(JNIEnv* env, jstring string, const jchar* chars) {
1476 CHECK_JNI_ENTRY(kFlag_Default | kFlag_ExcepOkay, "Esp", env, string, chars);
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001477 sc.CheckNonNull(chars);
1478 if (sc.ForceCopy()) {
1479 GuardedCopy::Check(__FUNCTION__, chars, false);
Elliott Hughesba8eee12012-01-24 20:25:24 -08001480 chars = reinterpret_cast<const jchar*>(GuardedCopy::Destroy(const_cast<jchar*>(chars)));
Elliott Hughesa2501992011-08-26 19:39:54 -07001481 }
1482 baseEnv(env)->ReleaseStringChars(env, string, chars);
1483 CHECK_JNI_EXIT_VOID();
1484 }
1485
1486 static jstring NewStringUTF(JNIEnv* env, const char* bytes) {
1487 CHECK_JNI_ENTRY(kFlag_NullableUtf, "Eu", env, bytes); // TODO: show pointer and truncate string.
1488 return CHECK_JNI_EXIT("s", baseEnv(env)->NewStringUTF(env, bytes));
1489 }
1490
1491 static jsize GetStringUTFLength(JNIEnv* env, jstring string) {
1492 CHECK_JNI_ENTRY(kFlag_CritOkay, "Es", env, string);
1493 return CHECK_JNI_EXIT("I", baseEnv(env)->GetStringUTFLength(env, string));
1494 }
1495
1496 static const char* GetStringUTFChars(JNIEnv* env, jstring string, jboolean* isCopy) {
1497 CHECK_JNI_ENTRY(kFlag_CritOkay, "Esp", env, string, isCopy);
1498 const char* result = baseEnv(env)->GetStringUTFChars(env, string, isCopy);
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001499 if (sc.ForceCopy() && result != NULL) {
1500 result = (const char*) GuardedCopy::Create(result, strlen(result) + 1, false);
Elliott Hughesa2501992011-08-26 19:39:54 -07001501 if (isCopy != NULL) {
1502 *isCopy = JNI_TRUE;
1503 }
1504 }
1505 return CHECK_JNI_EXIT("u", result); // TODO: show pointer and truncate string.
1506 }
1507
1508 static void ReleaseStringUTFChars(JNIEnv* env, jstring string, const char* utf) {
1509 CHECK_JNI_ENTRY(kFlag_ExcepOkay | kFlag_Release, "Esu", env, string, utf); // TODO: show pointer and truncate string.
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001510 if (sc.ForceCopy()) {
1511 GuardedCopy::Check(__FUNCTION__, utf, false);
Elliott Hughesba8eee12012-01-24 20:25:24 -08001512 utf = reinterpret_cast<const char*>(GuardedCopy::Destroy(const_cast<char*>(utf)));
Elliott Hughesa2501992011-08-26 19:39:54 -07001513 }
1514 baseEnv(env)->ReleaseStringUTFChars(env, string, utf);
1515 CHECK_JNI_EXIT_VOID();
1516 }
1517
1518 static jsize GetArrayLength(JNIEnv* env, jarray array) {
1519 CHECK_JNI_ENTRY(kFlag_CritOkay, "Ea", env, array);
1520 return CHECK_JNI_EXIT("I", baseEnv(env)->GetArrayLength(env, array));
1521 }
1522
1523 static jobjectArray NewObjectArray(JNIEnv* env, jsize length, jclass elementClass, jobject initialElement) {
1524 CHECK_JNI_ENTRY(kFlag_Default, "EzcL", env, length, elementClass, initialElement);
1525 return CHECK_JNI_EXIT("a", baseEnv(env)->NewObjectArray(env, length, elementClass, initialElement));
1526 }
1527
1528 static jobject GetObjectArrayElement(JNIEnv* env, jobjectArray array, jsize index) {
1529 CHECK_JNI_ENTRY(kFlag_Default, "EaI", env, array, index);
1530 return CHECK_JNI_EXIT("L", baseEnv(env)->GetObjectArrayElement(env, array, index));
1531 }
1532
1533 static void SetObjectArrayElement(JNIEnv* env, jobjectArray array, jsize index, jobject value) {
1534 CHECK_JNI_ENTRY(kFlag_Default, "EaIL", env, array, index, value);
1535 baseEnv(env)->SetObjectArrayElement(env, array, index, value);
1536 CHECK_JNI_EXIT_VOID();
1537 }
1538
1539#define NEW_PRIMITIVE_ARRAY(_artype, _jname) \
1540 static _artype New##_jname##Array(JNIEnv* env, jsize length) { \
1541 CHECK_JNI_ENTRY(kFlag_Default, "Ez", env, length); \
1542 return CHECK_JNI_EXIT("a", baseEnv(env)->New##_jname##Array(env, length)); \
1543 }
1544NEW_PRIMITIVE_ARRAY(jbooleanArray, Boolean);
1545NEW_PRIMITIVE_ARRAY(jbyteArray, Byte);
1546NEW_PRIMITIVE_ARRAY(jcharArray, Char);
1547NEW_PRIMITIVE_ARRAY(jshortArray, Short);
1548NEW_PRIMITIVE_ARRAY(jintArray, Int);
1549NEW_PRIMITIVE_ARRAY(jlongArray, Long);
1550NEW_PRIMITIVE_ARRAY(jfloatArray, Float);
1551NEW_PRIMITIVE_ARRAY(jdoubleArray, Double);
1552
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001553struct ForceCopyGetChecker {
Elliott Hughesba8eee12012-01-24 20:25:24 -08001554 public:
Elliott Hughesa2501992011-08-26 19:39:54 -07001555 ForceCopyGetChecker(ScopedCheck& sc, jboolean* isCopy) {
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001556 force_copy = sc.ForceCopy();
1557 no_copy = 0;
1558 if (force_copy && isCopy != NULL) {
Elliott Hughes3f6635a2012-06-19 13:37:49 -07001559 // Capture this before the base call tramples on it.
Elliott Hughesba8eee12012-01-24 20:25:24 -08001560 no_copy = *reinterpret_cast<uint32_t*>(isCopy);
Elliott Hughesa2501992011-08-26 19:39:54 -07001561 }
1562 }
1563
1564 template<typename ResultT>
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001565 ResultT Check(JNIEnv* env, jarray array, jboolean* isCopy, ResultT result) {
1566 if (force_copy && result != NULL) {
1567 if (no_copy != kNoCopyMagic) {
Elliott Hughesa2501992011-08-26 19:39:54 -07001568 result = reinterpret_cast<ResultT>(CreateGuardedPACopy(env, array, isCopy));
1569 }
1570 }
1571 return result;
1572 }
1573
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001574 uint32_t no_copy;
1575 bool force_copy;
Elliott Hughesa2501992011-08-26 19:39:54 -07001576};
1577
1578#define GET_PRIMITIVE_ARRAY_ELEMENTS(_ctype, _jname) \
1579 static _ctype* Get##_jname##ArrayElements(JNIEnv* env, _ctype##Array array, jboolean* isCopy) { \
1580 CHECK_JNI_ENTRY(kFlag_Default, "Eap", env, array, isCopy); \
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001581 _ctype* result = ForceCopyGetChecker(sc, isCopy).Check(env, array, isCopy, baseEnv(env)->Get##_jname##ArrayElements(env, array, isCopy)); \
Elliott Hughesa2501992011-08-26 19:39:54 -07001582 return CHECK_JNI_EXIT("p", result); \
1583 }
1584
1585#define RELEASE_PRIMITIVE_ARRAY_ELEMENTS(_ctype, _jname) \
1586 static void Release##_jname##ArrayElements(JNIEnv* env, _ctype##Array array, _ctype* elems, jint mode) { \
1587 CHECK_JNI_ENTRY(kFlag_Default | kFlag_ExcepOkay, "Eapr", env, array, elems, mode); \
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001588 sc.CheckNonNull(elems); \
1589 if (sc.ForceCopy()) { \
Elliott Hughesa2501992011-08-26 19:39:54 -07001590 ReleaseGuardedPACopy(env, array, elems, mode); \
1591 } \
1592 baseEnv(env)->Release##_jname##ArrayElements(env, array, elems, mode); \
1593 CHECK_JNI_EXIT_VOID(); \
1594 }
1595
1596#define GET_PRIMITIVE_ARRAY_REGION(_ctype, _jname) \
1597 static void Get##_jname##ArrayRegion(JNIEnv* env, _ctype##Array array, jsize start, jsize len, _ctype* buf) { \
1598 CHECK_JNI_ENTRY(kFlag_Default, "EaIIp", env, array, start, len, buf); \
1599 baseEnv(env)->Get##_jname##ArrayRegion(env, array, start, len, buf); \
1600 CHECK_JNI_EXIT_VOID(); \
1601 }
1602
1603#define SET_PRIMITIVE_ARRAY_REGION(_ctype, _jname) \
1604 static void Set##_jname##ArrayRegion(JNIEnv* env, _ctype##Array array, jsize start, jsize len, const _ctype* buf) { \
1605 CHECK_JNI_ENTRY(kFlag_Default, "EaIIp", env, array, start, len, buf); \
1606 baseEnv(env)->Set##_jname##ArrayRegion(env, array, start, len, buf); \
1607 CHECK_JNI_EXIT_VOID(); \
1608 }
1609
1610#define PRIMITIVE_ARRAY_FUNCTIONS(_ctype, _jname, _typechar) \
1611 GET_PRIMITIVE_ARRAY_ELEMENTS(_ctype, _jname); \
1612 RELEASE_PRIMITIVE_ARRAY_ELEMENTS(_ctype, _jname); \
1613 GET_PRIMITIVE_ARRAY_REGION(_ctype, _jname); \
1614 SET_PRIMITIVE_ARRAY_REGION(_ctype, _jname);
1615
Elliott Hughes3f6635a2012-06-19 13:37:49 -07001616// TODO: verify primitive array type matches call type.
Elliott Hughesa2501992011-08-26 19:39:54 -07001617PRIMITIVE_ARRAY_FUNCTIONS(jboolean, Boolean, 'Z');
1618PRIMITIVE_ARRAY_FUNCTIONS(jbyte, Byte, 'B');
1619PRIMITIVE_ARRAY_FUNCTIONS(jchar, Char, 'C');
1620PRIMITIVE_ARRAY_FUNCTIONS(jshort, Short, 'S');
1621PRIMITIVE_ARRAY_FUNCTIONS(jint, Int, 'I');
1622PRIMITIVE_ARRAY_FUNCTIONS(jlong, Long, 'J');
1623PRIMITIVE_ARRAY_FUNCTIONS(jfloat, Float, 'F');
1624PRIMITIVE_ARRAY_FUNCTIONS(jdouble, Double, 'D');
1625
Elliott Hughese84278b2012-03-22 10:06:53 -07001626 static jint RegisterNatives(JNIEnv* env, jclass c, const JNINativeMethod* methods, jint nMethods) {
1627 CHECK_JNI_ENTRY(kFlag_Default, "EcpI", env, c, methods, nMethods);
1628 return CHECK_JNI_EXIT("I", baseEnv(env)->RegisterNatives(env, c, methods, nMethods));
Elliott Hughesa2501992011-08-26 19:39:54 -07001629 }
1630
Elliott Hughese84278b2012-03-22 10:06:53 -07001631 static jint UnregisterNatives(JNIEnv* env, jclass c) {
1632 CHECK_JNI_ENTRY(kFlag_Default, "Ec", env, c);
1633 return CHECK_JNI_EXIT("I", baseEnv(env)->UnregisterNatives(env, c));
Elliott Hughesa2501992011-08-26 19:39:54 -07001634 }
1635
1636 static jint MonitorEnter(JNIEnv* env, jobject obj) {
1637 CHECK_JNI_ENTRY(kFlag_Default, "EL", env, obj);
Elliott Hughesa92853e2012-02-07 16:09:27 -08001638 if (!sc.CheckInstance(ScopedCheck::kObject, obj)) {
1639 return JNI_ERR; // Only for jni_internal_test. Real code will have aborted already.
1640 }
Elliott Hughesa2501992011-08-26 19:39:54 -07001641 return CHECK_JNI_EXIT("I", baseEnv(env)->MonitorEnter(env, obj));
1642 }
1643
1644 static jint MonitorExit(JNIEnv* env, jobject obj) {
1645 CHECK_JNI_ENTRY(kFlag_Default | kFlag_ExcepOkay, "EL", env, obj);
Elliott Hughesa92853e2012-02-07 16:09:27 -08001646 if (!sc.CheckInstance(ScopedCheck::kObject, obj)) {
1647 return JNI_ERR; // Only for jni_internal_test. Real code will have aborted already.
1648 }
Elliott Hughesa2501992011-08-26 19:39:54 -07001649 return CHECK_JNI_EXIT("I", baseEnv(env)->MonitorExit(env, obj));
1650 }
1651
1652 static jint GetJavaVM(JNIEnv *env, JavaVM **vm) {
1653 CHECK_JNI_ENTRY(kFlag_Default, "Ep", env, vm);
1654 return CHECK_JNI_EXIT("I", baseEnv(env)->GetJavaVM(env, vm));
1655 }
1656
1657 static void GetStringRegion(JNIEnv* env, jstring str, jsize start, jsize len, jchar* buf) {
1658 CHECK_JNI_ENTRY(kFlag_CritOkay, "EsIIp", env, str, start, len, buf);
1659 baseEnv(env)->GetStringRegion(env, str, start, len, buf);
1660 CHECK_JNI_EXIT_VOID();
1661 }
1662
1663 static void GetStringUTFRegion(JNIEnv* env, jstring str, jsize start, jsize len, char* buf) {
1664 CHECK_JNI_ENTRY(kFlag_CritOkay, "EsIIp", env, str, start, len, buf);
1665 baseEnv(env)->GetStringUTFRegion(env, str, start, len, buf);
1666 CHECK_JNI_EXIT_VOID();
1667 }
1668
1669 static void* GetPrimitiveArrayCritical(JNIEnv* env, jarray array, jboolean* isCopy) {
1670 CHECK_JNI_ENTRY(kFlag_CritGet, "Eap", env, array, isCopy);
1671 void* result = baseEnv(env)->GetPrimitiveArrayCritical(env, array, isCopy);
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001672 if (sc.ForceCopy() && result != NULL) {
Elliott Hughesa2501992011-08-26 19:39:54 -07001673 result = CreateGuardedPACopy(env, array, isCopy);
1674 }
1675 return CHECK_JNI_EXIT("p", result);
1676 }
1677
1678 static void ReleasePrimitiveArrayCritical(JNIEnv* env, jarray array, void* carray, jint mode) {
1679 CHECK_JNI_ENTRY(kFlag_CritRelease | kFlag_ExcepOkay, "Eapr", env, array, carray, mode);
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001680 sc.CheckNonNull(carray);
1681 if (sc.ForceCopy()) {
Elliott Hughesa2501992011-08-26 19:39:54 -07001682 ReleaseGuardedPACopy(env, array, carray, mode);
1683 }
1684 baseEnv(env)->ReleasePrimitiveArrayCritical(env, array, carray, mode);
1685 CHECK_JNI_EXIT_VOID();
1686 }
1687
1688 static const jchar* GetStringCritical(JNIEnv* env, jstring java_string, jboolean* isCopy) {
1689 CHECK_JNI_ENTRY(kFlag_CritGet, "Esp", env, java_string, isCopy);
1690 const jchar* result = baseEnv(env)->GetStringCritical(env, java_string, isCopy);
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001691 if (sc.ForceCopy() && result != NULL) {
Elliott Hughesa2501992011-08-26 19:39:54 -07001692 ScopedJniThreadState ts(env);
Ian Rogers365c1022012-06-22 15:05:28 -07001693 String* s = ts.Decode<String*>(java_string);
Elliott Hughesa2501992011-08-26 19:39:54 -07001694 int byteCount = s->GetLength() * 2;
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001695 result = (const jchar*) GuardedCopy::Create(result, byteCount, false);
Elliott Hughesa2501992011-08-26 19:39:54 -07001696 if (isCopy != NULL) {
1697 *isCopy = JNI_TRUE;
1698 }
1699 }
1700 return CHECK_JNI_EXIT("p", result);
1701 }
1702
1703 static void ReleaseStringCritical(JNIEnv* env, jstring string, const jchar* carray) {
1704 CHECK_JNI_ENTRY(kFlag_CritRelease | kFlag_ExcepOkay, "Esp", env, string, carray);
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001705 sc.CheckNonNull(carray);
1706 if (sc.ForceCopy()) {
1707 GuardedCopy::Check(__FUNCTION__, carray, false);
Elliott Hughesba8eee12012-01-24 20:25:24 -08001708 carray = reinterpret_cast<const jchar*>(GuardedCopy::Destroy(const_cast<jchar*>(carray)));
Elliott Hughesa2501992011-08-26 19:39:54 -07001709 }
1710 baseEnv(env)->ReleaseStringCritical(env, string, carray);
1711 CHECK_JNI_EXIT_VOID();
1712 }
1713
1714 static jweak NewWeakGlobalRef(JNIEnv* env, jobject obj) {
1715 CHECK_JNI_ENTRY(kFlag_Default, "EL", env, obj);
1716 return CHECK_JNI_EXIT("L", baseEnv(env)->NewWeakGlobalRef(env, obj));
1717 }
1718
1719 static jboolean ExceptionCheck(JNIEnv* env) {
1720 CHECK_JNI_ENTRY(kFlag_CritOkay | kFlag_ExcepOkay, "E", env);
1721 return CHECK_JNI_EXIT("b", baseEnv(env)->ExceptionCheck(env));
1722 }
1723
1724 static jobjectRefType GetObjectRefType(JNIEnv* env, jobject obj) {
1725 // Note: we use "Ep" rather than "EL" because this is the one JNI function
1726 // that it's okay to pass an invalid reference to.
1727 CHECK_JNI_ENTRY(kFlag_Default, "Ep", env, obj);
1728 // TODO: proper decoding of jobjectRefType!
1729 return CHECK_JNI_EXIT("I", baseEnv(env)->GetObjectRefType(env, obj));
1730 }
1731
1732 static jobject NewDirectByteBuffer(JNIEnv* env, void* address, jlong capacity) {
1733 CHECK_JNI_ENTRY(kFlag_Default, "EpJ", env, address, capacity);
1734 if (address == NULL) {
Elliott Hughes3f6635a2012-06-19 13:37:49 -07001735 JniAbortF(__FUNCTION__, "non-nullable address is NULL");
Elliott Hughesa2501992011-08-26 19:39:54 -07001736 }
1737 if (capacity <= 0) {
Elliott Hughes3f6635a2012-06-19 13:37:49 -07001738 JniAbortF(__FUNCTION__, "capacity must be greater than 0: %d", capacity);
Elliott Hughesa2501992011-08-26 19:39:54 -07001739 }
1740 return CHECK_JNI_EXIT("L", baseEnv(env)->NewDirectByteBuffer(env, address, capacity));
1741 }
1742
1743 static void* GetDirectBufferAddress(JNIEnv* env, jobject buf) {
1744 CHECK_JNI_ENTRY(kFlag_Default, "EL", env, buf);
1745 // TODO: check that 'buf' is a java.nio.Buffer.
1746 return CHECK_JNI_EXIT("p", baseEnv(env)->GetDirectBufferAddress(env, buf));
1747 }
1748
1749 static jlong GetDirectBufferCapacity(JNIEnv* env, jobject buf) {
1750 CHECK_JNI_ENTRY(kFlag_Default, "EL", env, buf);
1751 // TODO: check that 'buf' is a java.nio.Buffer.
1752 return CHECK_JNI_EXIT("J", baseEnv(env)->GetDirectBufferCapacity(env, buf));
1753 }
1754
1755 private:
1756 static inline const JNINativeInterface* baseEnv(JNIEnv* env) {
1757 return reinterpret_cast<JNIEnvExt*>(env)->unchecked_functions;
1758 }
1759};
1760
1761const JNINativeInterface gCheckNativeInterface = {
1762 NULL, // reserved0.
1763 NULL, // reserved1.
1764 NULL, // reserved2.
1765 NULL, // reserved3.
1766 CheckJNI::GetVersion,
1767 CheckJNI::DefineClass,
1768 CheckJNI::FindClass,
1769 CheckJNI::FromReflectedMethod,
1770 CheckJNI::FromReflectedField,
1771 CheckJNI::ToReflectedMethod,
1772 CheckJNI::GetSuperclass,
1773 CheckJNI::IsAssignableFrom,
1774 CheckJNI::ToReflectedField,
1775 CheckJNI::Throw,
1776 CheckJNI::ThrowNew,
1777 CheckJNI::ExceptionOccurred,
1778 CheckJNI::ExceptionDescribe,
1779 CheckJNI::ExceptionClear,
1780 CheckJNI::FatalError,
1781 CheckJNI::PushLocalFrame,
1782 CheckJNI::PopLocalFrame,
1783 CheckJNI::NewGlobalRef,
1784 CheckJNI::DeleteGlobalRef,
1785 CheckJNI::DeleteLocalRef,
1786 CheckJNI::IsSameObject,
1787 CheckJNI::NewLocalRef,
1788 CheckJNI::EnsureLocalCapacity,
1789 CheckJNI::AllocObject,
1790 CheckJNI::NewObject,
1791 CheckJNI::NewObjectV,
1792 CheckJNI::NewObjectA,
1793 CheckJNI::GetObjectClass,
1794 CheckJNI::IsInstanceOf,
1795 CheckJNI::GetMethodID,
1796 CheckJNI::CallObjectMethod,
1797 CheckJNI::CallObjectMethodV,
1798 CheckJNI::CallObjectMethodA,
1799 CheckJNI::CallBooleanMethod,
1800 CheckJNI::CallBooleanMethodV,
1801 CheckJNI::CallBooleanMethodA,
1802 CheckJNI::CallByteMethod,
1803 CheckJNI::CallByteMethodV,
1804 CheckJNI::CallByteMethodA,
1805 CheckJNI::CallCharMethod,
1806 CheckJNI::CallCharMethodV,
1807 CheckJNI::CallCharMethodA,
1808 CheckJNI::CallShortMethod,
1809 CheckJNI::CallShortMethodV,
1810 CheckJNI::CallShortMethodA,
1811 CheckJNI::CallIntMethod,
1812 CheckJNI::CallIntMethodV,
1813 CheckJNI::CallIntMethodA,
1814 CheckJNI::CallLongMethod,
1815 CheckJNI::CallLongMethodV,
1816 CheckJNI::CallLongMethodA,
1817 CheckJNI::CallFloatMethod,
1818 CheckJNI::CallFloatMethodV,
1819 CheckJNI::CallFloatMethodA,
1820 CheckJNI::CallDoubleMethod,
1821 CheckJNI::CallDoubleMethodV,
1822 CheckJNI::CallDoubleMethodA,
1823 CheckJNI::CallVoidMethod,
1824 CheckJNI::CallVoidMethodV,
1825 CheckJNI::CallVoidMethodA,
1826 CheckJNI::CallNonvirtualObjectMethod,
1827 CheckJNI::CallNonvirtualObjectMethodV,
1828 CheckJNI::CallNonvirtualObjectMethodA,
1829 CheckJNI::CallNonvirtualBooleanMethod,
1830 CheckJNI::CallNonvirtualBooleanMethodV,
1831 CheckJNI::CallNonvirtualBooleanMethodA,
1832 CheckJNI::CallNonvirtualByteMethod,
1833 CheckJNI::CallNonvirtualByteMethodV,
1834 CheckJNI::CallNonvirtualByteMethodA,
1835 CheckJNI::CallNonvirtualCharMethod,
1836 CheckJNI::CallNonvirtualCharMethodV,
1837 CheckJNI::CallNonvirtualCharMethodA,
1838 CheckJNI::CallNonvirtualShortMethod,
1839 CheckJNI::CallNonvirtualShortMethodV,
1840 CheckJNI::CallNonvirtualShortMethodA,
1841 CheckJNI::CallNonvirtualIntMethod,
1842 CheckJNI::CallNonvirtualIntMethodV,
1843 CheckJNI::CallNonvirtualIntMethodA,
1844 CheckJNI::CallNonvirtualLongMethod,
1845 CheckJNI::CallNonvirtualLongMethodV,
1846 CheckJNI::CallNonvirtualLongMethodA,
1847 CheckJNI::CallNonvirtualFloatMethod,
1848 CheckJNI::CallNonvirtualFloatMethodV,
1849 CheckJNI::CallNonvirtualFloatMethodA,
1850 CheckJNI::CallNonvirtualDoubleMethod,
1851 CheckJNI::CallNonvirtualDoubleMethodV,
1852 CheckJNI::CallNonvirtualDoubleMethodA,
1853 CheckJNI::CallNonvirtualVoidMethod,
1854 CheckJNI::CallNonvirtualVoidMethodV,
1855 CheckJNI::CallNonvirtualVoidMethodA,
1856 CheckJNI::GetFieldID,
1857 CheckJNI::GetObjectField,
1858 CheckJNI::GetBooleanField,
1859 CheckJNI::GetByteField,
1860 CheckJNI::GetCharField,
1861 CheckJNI::GetShortField,
1862 CheckJNI::GetIntField,
1863 CheckJNI::GetLongField,
1864 CheckJNI::GetFloatField,
1865 CheckJNI::GetDoubleField,
1866 CheckJNI::SetObjectField,
1867 CheckJNI::SetBooleanField,
1868 CheckJNI::SetByteField,
1869 CheckJNI::SetCharField,
1870 CheckJNI::SetShortField,
1871 CheckJNI::SetIntField,
1872 CheckJNI::SetLongField,
1873 CheckJNI::SetFloatField,
1874 CheckJNI::SetDoubleField,
1875 CheckJNI::GetStaticMethodID,
1876 CheckJNI::CallStaticObjectMethod,
1877 CheckJNI::CallStaticObjectMethodV,
1878 CheckJNI::CallStaticObjectMethodA,
1879 CheckJNI::CallStaticBooleanMethod,
1880 CheckJNI::CallStaticBooleanMethodV,
1881 CheckJNI::CallStaticBooleanMethodA,
1882 CheckJNI::CallStaticByteMethod,
1883 CheckJNI::CallStaticByteMethodV,
1884 CheckJNI::CallStaticByteMethodA,
1885 CheckJNI::CallStaticCharMethod,
1886 CheckJNI::CallStaticCharMethodV,
1887 CheckJNI::CallStaticCharMethodA,
1888 CheckJNI::CallStaticShortMethod,
1889 CheckJNI::CallStaticShortMethodV,
1890 CheckJNI::CallStaticShortMethodA,
1891 CheckJNI::CallStaticIntMethod,
1892 CheckJNI::CallStaticIntMethodV,
1893 CheckJNI::CallStaticIntMethodA,
1894 CheckJNI::CallStaticLongMethod,
1895 CheckJNI::CallStaticLongMethodV,
1896 CheckJNI::CallStaticLongMethodA,
1897 CheckJNI::CallStaticFloatMethod,
1898 CheckJNI::CallStaticFloatMethodV,
1899 CheckJNI::CallStaticFloatMethodA,
1900 CheckJNI::CallStaticDoubleMethod,
1901 CheckJNI::CallStaticDoubleMethodV,
1902 CheckJNI::CallStaticDoubleMethodA,
1903 CheckJNI::CallStaticVoidMethod,
1904 CheckJNI::CallStaticVoidMethodV,
1905 CheckJNI::CallStaticVoidMethodA,
1906 CheckJNI::GetStaticFieldID,
1907 CheckJNI::GetStaticObjectField,
1908 CheckJNI::GetStaticBooleanField,
1909 CheckJNI::GetStaticByteField,
1910 CheckJNI::GetStaticCharField,
1911 CheckJNI::GetStaticShortField,
1912 CheckJNI::GetStaticIntField,
1913 CheckJNI::GetStaticLongField,
1914 CheckJNI::GetStaticFloatField,
1915 CheckJNI::GetStaticDoubleField,
1916 CheckJNI::SetStaticObjectField,
1917 CheckJNI::SetStaticBooleanField,
1918 CheckJNI::SetStaticByteField,
1919 CheckJNI::SetStaticCharField,
1920 CheckJNI::SetStaticShortField,
1921 CheckJNI::SetStaticIntField,
1922 CheckJNI::SetStaticLongField,
1923 CheckJNI::SetStaticFloatField,
1924 CheckJNI::SetStaticDoubleField,
1925 CheckJNI::NewString,
1926 CheckJNI::GetStringLength,
1927 CheckJNI::GetStringChars,
1928 CheckJNI::ReleaseStringChars,
1929 CheckJNI::NewStringUTF,
1930 CheckJNI::GetStringUTFLength,
1931 CheckJNI::GetStringUTFChars,
1932 CheckJNI::ReleaseStringUTFChars,
1933 CheckJNI::GetArrayLength,
1934 CheckJNI::NewObjectArray,
1935 CheckJNI::GetObjectArrayElement,
1936 CheckJNI::SetObjectArrayElement,
1937 CheckJNI::NewBooleanArray,
1938 CheckJNI::NewByteArray,
1939 CheckJNI::NewCharArray,
1940 CheckJNI::NewShortArray,
1941 CheckJNI::NewIntArray,
1942 CheckJNI::NewLongArray,
1943 CheckJNI::NewFloatArray,
1944 CheckJNI::NewDoubleArray,
1945 CheckJNI::GetBooleanArrayElements,
1946 CheckJNI::GetByteArrayElements,
1947 CheckJNI::GetCharArrayElements,
1948 CheckJNI::GetShortArrayElements,
1949 CheckJNI::GetIntArrayElements,
1950 CheckJNI::GetLongArrayElements,
1951 CheckJNI::GetFloatArrayElements,
1952 CheckJNI::GetDoubleArrayElements,
1953 CheckJNI::ReleaseBooleanArrayElements,
1954 CheckJNI::ReleaseByteArrayElements,
1955 CheckJNI::ReleaseCharArrayElements,
1956 CheckJNI::ReleaseShortArrayElements,
1957 CheckJNI::ReleaseIntArrayElements,
1958 CheckJNI::ReleaseLongArrayElements,
1959 CheckJNI::ReleaseFloatArrayElements,
1960 CheckJNI::ReleaseDoubleArrayElements,
1961 CheckJNI::GetBooleanArrayRegion,
1962 CheckJNI::GetByteArrayRegion,
1963 CheckJNI::GetCharArrayRegion,
1964 CheckJNI::GetShortArrayRegion,
1965 CheckJNI::GetIntArrayRegion,
1966 CheckJNI::GetLongArrayRegion,
1967 CheckJNI::GetFloatArrayRegion,
1968 CheckJNI::GetDoubleArrayRegion,
1969 CheckJNI::SetBooleanArrayRegion,
1970 CheckJNI::SetByteArrayRegion,
1971 CheckJNI::SetCharArrayRegion,
1972 CheckJNI::SetShortArrayRegion,
1973 CheckJNI::SetIntArrayRegion,
1974 CheckJNI::SetLongArrayRegion,
1975 CheckJNI::SetFloatArrayRegion,
1976 CheckJNI::SetDoubleArrayRegion,
1977 CheckJNI::RegisterNatives,
1978 CheckJNI::UnregisterNatives,
1979 CheckJNI::MonitorEnter,
1980 CheckJNI::MonitorExit,
1981 CheckJNI::GetJavaVM,
1982 CheckJNI::GetStringRegion,
1983 CheckJNI::GetStringUTFRegion,
1984 CheckJNI::GetPrimitiveArrayCritical,
1985 CheckJNI::ReleasePrimitiveArrayCritical,
1986 CheckJNI::GetStringCritical,
1987 CheckJNI::ReleaseStringCritical,
1988 CheckJNI::NewWeakGlobalRef,
1989 CheckJNI::DeleteWeakGlobalRef,
1990 CheckJNI::ExceptionCheck,
1991 CheckJNI::NewDirectByteBuffer,
1992 CheckJNI::GetDirectBufferAddress,
1993 CheckJNI::GetDirectBufferCapacity,
1994 CheckJNI::GetObjectRefType,
1995};
1996
1997const JNINativeInterface* GetCheckJniNativeInterface() {
1998 return &gCheckNativeInterface;
1999}
2000
2001class CheckJII {
Elliott Hughesba8eee12012-01-24 20:25:24 -08002002 public:
Elliott Hughesa2501992011-08-26 19:39:54 -07002003 static jint DestroyJavaVM(JavaVM* vm) {
Elliott Hughesa0957642011-09-02 14:27:33 -07002004 ScopedCheck sc(vm, false, __FUNCTION__);
Elliott Hughes32ae6e32011-09-27 10:46:50 -07002005 sc.Check(true, "v", vm);
2006 return CHECK_JNI_EXIT("I", BaseVm(vm)->DestroyJavaVM(vm));
Elliott Hughesa2501992011-08-26 19:39:54 -07002007 }
2008
2009 static jint AttachCurrentThread(JavaVM* vm, JNIEnv** p_env, void* thr_args) {
Elliott Hughesa0957642011-09-02 14:27:33 -07002010 ScopedCheck sc(vm, false, __FUNCTION__);
Elliott Hughes32ae6e32011-09-27 10:46:50 -07002011 sc.Check(true, "vpp", vm, p_env, thr_args);
2012 return CHECK_JNI_EXIT("I", BaseVm(vm)->AttachCurrentThread(vm, p_env, thr_args));
Elliott Hughesa2501992011-08-26 19:39:54 -07002013 }
2014
2015 static jint AttachCurrentThreadAsDaemon(JavaVM* vm, JNIEnv** p_env, void* thr_args) {
Elliott Hughesa0957642011-09-02 14:27:33 -07002016 ScopedCheck sc(vm, false, __FUNCTION__);
Elliott Hughes32ae6e32011-09-27 10:46:50 -07002017 sc.Check(true, "vpp", vm, p_env, thr_args);
2018 return CHECK_JNI_EXIT("I", BaseVm(vm)->AttachCurrentThreadAsDaemon(vm, p_env, thr_args));
Elliott Hughesa2501992011-08-26 19:39:54 -07002019 }
2020
2021 static jint DetachCurrentThread(JavaVM* vm) {
Elliott Hughesa0957642011-09-02 14:27:33 -07002022 ScopedCheck sc(vm, true, __FUNCTION__);
Elliott Hughes32ae6e32011-09-27 10:46:50 -07002023 sc.Check(true, "v", vm);
2024 return CHECK_JNI_EXIT("I", BaseVm(vm)->DetachCurrentThread(vm));
Elliott Hughesa2501992011-08-26 19:39:54 -07002025 }
2026
2027 static jint GetEnv(JavaVM* vm, void** env, jint version) {
Elliott Hughesa0957642011-09-02 14:27:33 -07002028 ScopedCheck sc(vm, true, __FUNCTION__);
Elliott Hughes32ae6e32011-09-27 10:46:50 -07002029 sc.Check(true, "v", vm);
2030 return CHECK_JNI_EXIT("I", BaseVm(vm)->GetEnv(vm, env, version));
Elliott Hughesa2501992011-08-26 19:39:54 -07002031 }
2032
2033 private:
Elliott Hughes32ae6e32011-09-27 10:46:50 -07002034 static inline const JNIInvokeInterface* BaseVm(JavaVM* vm) {
Elliott Hughesa2501992011-08-26 19:39:54 -07002035 return reinterpret_cast<JavaVMExt*>(vm)->unchecked_functions;
2036 }
2037};
2038
2039const JNIInvokeInterface gCheckInvokeInterface = {
2040 NULL, // reserved0
2041 NULL, // reserved1
2042 NULL, // reserved2
2043 CheckJII::DestroyJavaVM,
2044 CheckJII::AttachCurrentThread,
2045 CheckJII::DetachCurrentThread,
2046 CheckJII::GetEnv,
2047 CheckJII::AttachCurrentThreadAsDaemon
2048};
2049
2050const JNIInvokeInterface* GetCheckJniInvokeInterface() {
2051 return &gCheckInvokeInterface;
2052}
2053
2054} // namespace art