blob: 130acef219b51fc5024519b8447438b1250828cb [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"
24#include "thread.h"
25
26namespace art {
27
28void JniAbort(const char* jni_function_name) {
29 std::stringstream os;
30
31 // dvmDumpThread(dvmThreadSelf(), false);
32 os << "JNI app bug detected";
33
34 if (jni_function_name != NULL) {
35 os << "\n in call to " << jni_function_name;
36 }
37 // TODO: say what native method we're in...
38 //const Method* method = dvmGetCurrentJNIMethod();
39 //os << "\n in " << PrettyMethod(method);
40
41 JavaVMExt* vm = Runtime::Current()->GetJavaVM();
42 if (vm->check_jni_abort_hook != NULL) {
43 vm->check_jni_abort_hook(os.str());
44 } else {
45 LOG(FATAL) << os.str();
46 }
47}
48
49/*
50 * ===========================================================================
51 * JNI function helpers
52 * ===========================================================================
53 */
54
55// TODO: remove this ODR violation!
56class ScopedJniThreadState {
57 public:
58 explicit ScopedJniThreadState(JNIEnv* env)
59 : env_(reinterpret_cast<JNIEnvExt*>(env)) {
60 self_ = ThreadForEnv(env);
61 self_->SetState(Thread::kRunnable);
62 }
63
64 ~ScopedJniThreadState() {
65 self_->SetState(Thread::kNative);
66 }
67
68 JNIEnvExt* Env() {
69 return env_;
70 }
71
72 Thread* Self() {
73 return self_;
74 }
75
76 JavaVMExt* Vm() {
77 return env_->vm;
78 }
79
80 private:
81 static Thread* ThreadForEnv(JNIEnv* env) {
82 // TODO: need replacement for gDvmJni.
83 bool workAroundAppJniBugs = true;
84 Thread* env_self = reinterpret_cast<JNIEnvExt*>(env)->self;
85 Thread* self = workAroundAppJniBugs ? Thread::Current() : env_self;
86 if (self != env_self) {
87 LOG(ERROR) << "JNI ERROR: JNIEnv for " << *env_self
88 << " used on " << *self;
89 // TODO: dump stack
90 }
91 return self;
92 }
93
94 JNIEnvExt* env_;
95 Thread* self_;
96 DISALLOW_COPY_AND_ASSIGN(ScopedJniThreadState);
97};
98
99template<typename T>
100T Decode(ScopedJniThreadState& ts, jobject obj) {
101 return reinterpret_cast<T>(ts.Self()->DecodeJObject(obj));
102}
103
104/* for IsValidMemberNameUtf8(), a bit vector indicating valid low ascii */
105uint32_t DEX_MEMBER_VALID_LOW_ASCII[4] = {
106 0x00000000, // 00..1f low control characters; nothing valid
107 0x03ff2010, // 20..3f digits and symbols; valid: '0'..'9', '$', '-'
108 0x87fffffe, // 40..5f uppercase etc.; valid: 'A'..'Z', '_'
109 0x07fffffe // 60..7f lowercase etc.; valid: 'a'..'z'
110};
111
112/* Helper for IsValidMemberNameUtf8(); do not call directly. */
113bool IsValidMemberNameUtf8Slow(const char** pUtf8Ptr) {
114 /*
115 * It's a multibyte encoded character. Decode it and analyze. We
116 * accept anything that isn't (a) an improperly encoded low value,
117 * (b) an improper surrogate pair, (c) an encoded '\0', (d) a high
118 * control character, or (e) a high space, layout, or special
119 * character (U+00a0, U+2000..U+200f, U+2028..U+202f,
120 * U+fff0..U+ffff). This is all specified in the dex format
121 * document.
122 */
123
124 uint16_t utf16 = GetUtf16FromUtf8(pUtf8Ptr);
125
126 // Perform follow-up tests based on the high 8 bits.
127 switch (utf16 >> 8) {
128 case 0x00:
129 // It's only valid if it's above the ISO-8859-1 high space (0xa0).
130 return (utf16 > 0x00a0);
131 case 0xd8:
132 case 0xd9:
133 case 0xda:
134 case 0xdb:
135 // It's a leading surrogate. Check to see that a trailing
136 // surrogate follows.
137 utf16 = GetUtf16FromUtf8(pUtf8Ptr);
138 return (utf16 >= 0xdc00) && (utf16 <= 0xdfff);
139 case 0xdc:
140 case 0xdd:
141 case 0xde:
142 case 0xdf:
143 // It's a trailing surrogate, which is not valid at this point.
144 return false;
145 case 0x20:
146 case 0xff:
147 // It's in the range that has spaces, controls, and specials.
148 switch (utf16 & 0xfff8) {
149 case 0x2000:
150 case 0x2008:
151 case 0x2028:
152 case 0xfff0:
153 case 0xfff8:
154 return false;
155 }
156 break;
157 }
158 return true;
159}
160
161/* Return whether the pointed-at modified-UTF-8 encoded character is
162 * valid as part of a member name, updating the pointer to point past
163 * the consumed character. This will consume two encoded UTF-16 code
164 * points if the character is encoded as a surrogate pair. Also, if
165 * this function returns false, then the given pointer may only have
166 * been partially advanced.
167 */
168bool IsValidMemberNameUtf8(const char** pUtf8Ptr) {
169 uint8_t c = (uint8_t) **pUtf8Ptr;
170 if (c <= 0x7f) {
171 // It's low-ascii, so check the table.
172 uint32_t wordIdx = c >> 5;
173 uint32_t bitIdx = c & 0x1f;
174 (*pUtf8Ptr)++;
175 return (DEX_MEMBER_VALID_LOW_ASCII[wordIdx] & (1 << bitIdx)) != 0;
176 }
177
178 // It's a multibyte encoded character. Call a non-inline function
179 // for the heavy lifting.
180 return IsValidMemberNameUtf8Slow(pUtf8Ptr);
181}
182
183bool IsValidClassName(const char* s, bool isClassName, bool dotSeparator) {
184 int arrayCount = 0;
185
186 while (*s == '[') {
187 arrayCount++;
188 s++;
189 }
190
191 if (arrayCount > 255) {
192 // Arrays may have no more than 255 dimensions.
193 return false;
194 }
195
196 if (arrayCount != 0) {
197 /*
198 * If we're looking at an array of some sort, then it doesn't
199 * matter if what is being asked for is a class name; the
200 * format looks the same as a type descriptor in that case, so
201 * treat it as such.
202 */
203 isClassName = false;
204 }
205
206 if (!isClassName) {
207 /*
208 * We are looking for a descriptor. Either validate it as a
209 * single-character primitive type, or continue on to check the
210 * embedded class name (bracketed by "L" and ";").
211 */
212 switch (*(s++)) {
213 case 'B':
214 case 'C':
215 case 'D':
216 case 'F':
217 case 'I':
218 case 'J':
219 case 'S':
220 case 'Z':
221 // These are all single-character descriptors for primitive types.
222 return (*s == '\0');
223 case 'V':
224 // Non-array void is valid, but you can't have an array of void.
225 return (arrayCount == 0) && (*s == '\0');
226 case 'L':
227 // Class name: Break out and continue below.
228 break;
229 default:
230 // Oddball descriptor character.
231 return false;
232 }
233 }
234
235 /*
236 * We just consumed the 'L' that introduces a class name as part
237 * of a type descriptor, or we are looking for an unadorned class
238 * name.
239 */
240
241 bool sepOrFirst = true; // first character or just encountered a separator.
242 for (;;) {
243 uint8_t c = (uint8_t) *s;
244 switch (c) {
245 case '\0':
246 /*
247 * Premature end for a type descriptor, but valid for
248 * a class name as long as we haven't encountered an
249 * empty component (including the degenerate case of
250 * the empty string "").
251 */
252 return isClassName && !sepOrFirst;
253 case ';':
254 /*
255 * Invalid character for a class name, but the
256 * legitimate end of a type descriptor. In the latter
257 * case, make sure that this is the end of the string
258 * and that it doesn't end with an empty component
259 * (including the degenerate case of "L;").
260 */
261 return !isClassName && !sepOrFirst && (s[1] == '\0');
262 case '/':
263 case '.':
264 if (dotSeparator != (c == '.')) {
265 // The wrong separator character.
266 return false;
267 }
268 if (sepOrFirst) {
269 // Separator at start or two separators in a row.
270 return false;
271 }
272 sepOrFirst = true;
273 s++;
274 break;
275 default:
276 if (!IsValidMemberNameUtf8(&s)) {
277 return false;
278 }
279 sepOrFirst = false;
280 break;
281 }
282 }
283}
284
285/*
286 * Hack to allow forcecopy to work with jniGetNonMovableArrayElements.
287 * The code deliberately uses an invalid sequence of operations, so we
288 * need to pass it through unmodified. Review that code before making
289 * any changes here.
290 */
291#define kNoCopyMagic 0xd5aab57f
292
293/*
294 * Flags passed into ScopedCheck.
295 */
296#define kFlag_Default 0x0000
297
298#define kFlag_CritBad 0x0000 /* calling while in critical is bad */
299#define kFlag_CritOkay 0x0001 /* ...okay */
300#define kFlag_CritGet 0x0002 /* this is a critical "get" */
301#define kFlag_CritRelease 0x0003 /* this is a critical "release" */
302#define kFlag_CritMask 0x0003 /* bit mask to get "crit" value */
303
304#define kFlag_ExcepBad 0x0000 /* raised exceptions are bad */
305#define kFlag_ExcepOkay 0x0004 /* ...okay */
306
307#define kFlag_Release 0x0010 /* are we in a non-critical release function? */
308#define kFlag_NullableUtf 0x0020 /* are our UTF parameters nullable? */
309
310#define kFlag_Invocation 0x8000 /* Part of the invocation interface (JavaVM*) */
311
312class ScopedCheck {
313public:
314 // For JNIEnv* functions.
315 explicit ScopedCheck(JNIEnv* env, int flags, const char* functionName) {
316 init(env, flags, functionName, true);
317 checkThread(flags);
318 }
319
320 // For JavaVM* functions.
321 explicit ScopedCheck(bool hasMethod, const char* functionName) {
322 init(NULL, kFlag_Invocation, functionName, hasMethod);
323 }
324
325 bool forceCopy() {
326 return Runtime::Current()->GetJavaVM()->force_copy;
327 }
328
329 /*
330 * In some circumstances the VM will screen class names, but it doesn't
331 * for class lookup. When things get bounced through a class loader, they
332 * can actually get normalized a couple of times; as a result, passing in
333 * a class name like "java.lang.Thread" instead of "java/lang/Thread" will
334 * work in some circumstances.
335 *
336 * This is incorrect and could cause strange behavior or compatibility
337 * problems, so we want to screen that out here.
338 *
339 * We expect "fully-qualified" class names, like "java/lang/Thread" or
340 * "[Ljava/lang/Object;".
341 */
342 void checkClassName(const char* className) {
343 if (!IsValidClassName(className, true, false)) {
344 LOG(ERROR) << "JNI ERROR: illegal class name '" << className << "' (" << mFunctionName << ")\n"
345 << " (should be of the form 'java/lang/String', [Ljava/lang/String;' or '[[B')\n";
346 JniAbort();
347 }
348 }
349
350 /*
351 * Verify that the field is of the appropriate type. If the field has an
352 * object type, "java_object" is the object we're trying to assign into it.
353 *
354 * Works for both static and instance fields.
355 */
356 void checkFieldType(jobject java_object, jfieldID fid, char prim, bool isStatic) {
357 if (fid == NULL) {
358 LOG(ERROR) << "JNI ERROR: null jfieldID";
359 JniAbort();
360 return;
361 }
362
363 ScopedJniThreadState ts(mEnv);
364 Field* f = DecodeField(ts, fid);
365 if ((f->GetType() == 'L' || f->GetType() == '[') && java_object != NULL) {
366 Object* obj = Decode<Object*>(ts, java_object);
367 /*
368 * If java_object is a weak global ref whose referent has been cleared,
369 * obj will be NULL. Otherwise, obj should always be non-NULL
370 * and valid.
371 */
372 if (obj != NULL && !Heap::IsHeapAddress(obj)) {
373 LOG(ERROR) << "JNI ERROR: field operation on invalid " << GetIndirectRefKind(java_object) << ": " << java_object;
374 JniAbort();
375 return;
376 } else {
377#if 0
378 Class* field_class = dvmFindLoadedClass(f->signature);
379 if (!obj->GetClass()->InstanceOf(field_class)) {
380 LOG(ERROR) << "JNI ERROR: attempt to set field " << PrettyField(f) << " with value of wrong type: " << PrettyType(java_object);
381 JniAbort();
382 return;
383 }
384#else
385 UNIMPLEMENTED(WARNING) << "need way to get Class* for a given Field*'s type";
386#endif
387 }
388 } else if (f->GetType() != prim) {
389 LOG(ERROR) << "JNI ERROR: attempt to set field " << PrettyField(f) << " with value of wrong type: " << prim;
390 JniAbort();
391 return;
392 } else if (isStatic && !f->IsStatic()) {
393 if (isStatic) {
394 LOG(ERROR) << "JNI ERROR: accessing non-static field " << PrettyField(f) << " as static";
395 } else {
396 LOG(ERROR) << "JNI ERROR: accessing static field " << PrettyField(f) << " as non-static";
397 }
398 JniAbort();
399 return;
400 }
401 }
402
403 /*
404 * Verify that this instance field ID is valid for this object.
405 *
406 * Assumes "jobj" has already been validated.
407 */
408 void checkInstanceFieldID(jobject java_object, jfieldID fid) {
409 ScopedJniThreadState ts(mEnv);
410
411 Object* o = Decode<Object*>(ts, java_object);
412 if (!Heap::IsHeapAddress(o)) {
413 LOG(ERROR) << "JNI ERROR: field operation on invalid " << GetIndirectRefKind(java_object) << ": " << java_object;
414 JniAbort();
415 return;
416 }
417
418 Field* f = DecodeField(ts, fid);
419 Class* c = o->GetClass();
420 if (c->FindInstanceField(f->GetName()->ToModifiedUtf8(), f->GetDescriptor()) == NULL) {
421 LOG(ERROR) << "JNI ERROR: jfieldID " << PrettyField(f) << " not valid for an object of class " << PrettyType(o);
422 JniAbort();
423 }
424 }
425
426 /*
427 * Verify that the pointer value is non-NULL.
428 */
429 void checkNonNull(const void* ptr) {
430 if (ptr == NULL) {
431 LOG(ERROR) << "JNI ERROR: invalid null pointer";
432 JniAbort();
433 }
434 }
435
436 /*
437 * Verify that the method's return type matches the type of call.
438 * 'expectedType' will be "L" for all objects, including arrays.
439 */
440 void checkSig(jmethodID mid, const char* expectedType, bool isStatic) {
441 ScopedJniThreadState ts(mEnv);
442 const Method* m = DecodeMethod(ts, mid);
443 if (*expectedType != m->GetShorty()[0]) {
444 LOG(ERROR) << "JNI ERROR: expected return type '%s' calling " << PrettyMethod(m);
445 JniAbort();
446 } else if (isStatic && !m->IsStatic()) {
447 if (isStatic) {
448 LOG(ERROR) << "JNI ERROR: calling non-static method " << PrettyMethod(m) << " with static call";
449 } else {
450 LOG(ERROR) << "JNI ERROR: calling static method " << PrettyMethod(m) << " with non-static call";
451 }
452 JniAbort();
453 }
454 }
455
456 /*
457 * Verify that this static field ID is valid for this class.
458 *
459 * Assumes "java_class" has already been validated.
460 */
461 void checkStaticFieldID(jclass java_class, jfieldID fid) {
462 ScopedJniThreadState ts(mEnv);
463 Class* c = Decode<Class*>(ts, java_class);
464 const Field* f = DecodeField(ts, fid);
465 if (f->GetDeclaringClass() != c) {
466 LOG(ERROR) << "JNI ERROR: static jfieldID " << fid << " not valid for class " << PrettyDescriptor(c->GetDescriptor());
467 JniAbort();
468 }
469 }
470
471 /*
472 * Verify that "mid" is appropriate for "clazz".
473 *
474 * A mismatch isn't dangerous, because the jmethodID defines the class. In
475 * fact, jclazz is unused in the implementation. It's best if we don't
476 * allow bad code in the system though.
477 *
478 * Instances of "jclazz" must be instances of the method's declaring class.
479 */
480 void checkStaticMethod(jclass java_class, jmethodID mid) {
481 ScopedJniThreadState ts(mEnv);
482 Class* c = Decode<Class*>(ts, java_class);
483 const Method* m = DecodeMethod(ts, mid);
484 if (!c->IsAssignableFrom(m->GetDeclaringClass())) {
485 LOG(ERROR) << "JNI ERROR: can't call static " << PrettyMethod(m) << " on class " << PrettyDescriptor(c->GetDescriptor());
486 JniAbort();
487 }
488 }
489
490 /*
491 * Verify that "mid" is appropriate for "jobj".
492 *
493 * Make sure the object is an instance of the method's declaring class.
494 * (Note the mid might point to a declaration in an interface; this
495 * will be handled automatically by the instanceof check.)
496 */
497 void checkVirtualMethod(jobject java_object, jmethodID mid) {
498 ScopedJniThreadState ts(mEnv);
499 Object* o = Decode<Object*>(ts, java_object);
500 const Method* m = DecodeMethod(ts, mid);
501 if (!o->InstanceOf(m->GetDeclaringClass())) {
502 LOG(ERROR) << "JNI ERROR: can't call " << PrettyMethod(m) << " on instance of " << PrettyType(o);
503 JniAbort();
504 }
505 }
506
507 /**
508 * The format string is a sequence of the following characters,
509 * and must be followed by arguments of the corresponding types
510 * in the same order.
511 *
512 * Java primitive types:
513 * B - jbyte
514 * C - jchar
515 * D - jdouble
516 * F - jfloat
517 * I - jint
518 * J - jlong
519 * S - jshort
520 * Z - jboolean (shown as true and false)
521 * V - void
522 *
523 * Java reference types:
524 * L - jobject
525 * a - jarray
526 * c - jclass
527 * s - jstring
528 *
529 * JNI types:
530 * b - jboolean (shown as JNI_TRUE and JNI_FALSE)
531 * f - jfieldID
532 * m - jmethodID
533 * p - void*
534 * r - jint (for release mode arguments)
535 * u - const char* (modified UTF-8)
536 * z - jsize (for lengths; use i if negative values are okay)
537 * v - JavaVM*
538 * E - JNIEnv*
539 * . - no argument; just print "..." (used for varargs JNI calls)
540 *
541 * Use the kFlag_NullableUtf flag where 'u' field(s) are nullable.
542 */
543 void check(bool entry, const char* fmt0, ...) {
544 va_list ap;
545
546 bool shouldTrace = false;
547 const Method* method = NULL;
548#if 0
549 if ((gDvm.jniTrace || gDvmJni.logThirdPartyJni) && mHasMethod) {
550 // We need to guard some of the invocation interface's calls: a bad caller might
551 // use DetachCurrentThread or GetEnv on a thread that's not yet attached.
552 if ((mFlags & kFlag_Invocation) == 0 || dvmThreadSelf() != NULL) {
553 method = dvmGetCurrentJNIMethod();
554 }
555 }
556 if (method != NULL) {
557 // If both "-Xcheck:jni" and "-Xjnitrace:" are enabled, we print trace messages
558 // when a native method that matches the Xjnitrace argument calls a JNI function
559 // such as NewByteArray.
560 if (gDvm.jniTrace && strstr(method->clazz->descriptor, gDvm.jniTrace) != NULL) {
561 shouldTrace = true;
562 }
563 // If -Xjniopts:logThirdPartyJni is on, we want to log any JNI function calls
564 // made by a third-party native method.
565 if (gDvmJni.logThirdPartyJni) {
566 shouldTrace |= method->shouldTrace;
567 }
568 }
569#endif
570 if (shouldTrace) {
571 va_start(ap, fmt0);
572 std::string msg;
573 for (const char* fmt = fmt0; *fmt;) {
574 char ch = *fmt++;
575 if (ch == 'B') { // jbyte
576 jbyte b = va_arg(ap, int);
577 if (b >= 0 && b < 10) {
578 StringAppendF(&msg, "%d", b);
579 } else {
580 StringAppendF(&msg, "%#x (%d)", b, b);
581 }
582 } else if (ch == 'C') { // jchar
583 jchar c = va_arg(ap, int);
584 if (c < 0x7f && c >= ' ') {
585 StringAppendF(&msg, "U+%x ('%c')", c, c);
586 } else {
587 StringAppendF(&msg, "U+%x", c);
588 }
589 } else if (ch == 'F' || ch == 'D') { // jfloat, jdouble
590 StringAppendF(&msg, "%g", va_arg(ap, double));
591 } else if (ch == 'I' || ch == 'S') { // jint, jshort
592 StringAppendF(&msg, "%d", va_arg(ap, int));
593 } else if (ch == 'J') { // jlong
594 StringAppendF(&msg, "%lld", va_arg(ap, jlong));
595 } else if (ch == 'Z') { // jboolean
596 StringAppendF(&msg, "%s", va_arg(ap, int) ? "true" : "false");
597 } else if (ch == 'V') { // void
598 msg += "void";
599 } else if (ch == 'v') { // JavaVM*
600 JavaVM* vm = va_arg(ap, JavaVM*);
601 StringAppendF(&msg, "(JavaVM*)%p", vm);
602 } else if (ch == 'E') { // JNIEnv*
603 JNIEnv* env = va_arg(ap, JNIEnv*);
604 StringAppendF(&msg, "(JNIEnv*)%p", env);
605 } else if (ch == 'L' || ch == 'a' || ch == 's') { // jobject, jarray, jstring
606 // For logging purposes, these are identical.
607 jobject o = va_arg(ap, jobject);
608 if (o == NULL) {
609 msg += "NULL";
610 } else {
611 StringAppendF(&msg, "%p", o);
612 }
613 } else if (ch == 'b') { // jboolean (JNI-style)
614 jboolean b = va_arg(ap, int);
615 msg += (b ? "JNI_TRUE" : "JNI_FALSE");
616 } else if (ch == 'c') { // jclass
617 jclass jc = va_arg(ap, jclass);
618 Class* c = reinterpret_cast<Class*>(Thread::Current()->DecodeJObject(jc));
619 if (c == NULL) {
620 msg += "NULL";
621 } else if (c == kInvalidIndirectRefObject || !Heap::IsHeapAddress(c)) {
622 StringAppendF(&msg, "%p(INVALID)", jc);
623 } else {
624 msg += PrettyDescriptor(c->GetDescriptor());
625 if (!entry) {
626 StringAppendF(&msg, " (%p)", jc);
627 }
628 }
629 } else if (ch == 'f') { // jfieldID
630 jfieldID fid = va_arg(ap, jfieldID);
631 Field* f = reinterpret_cast<Field*>(Thread::Current()->DecodeJObject(reinterpret_cast<jweak>(fid)));
632 msg += PrettyField(f);
633 if (!entry) {
634 StringAppendF(&msg, " (%p)", fid);
635 }
636 } else if (ch == 'z') { // non-negative jsize
637 // You might expect jsize to be size_t, but it's not; it's the same as jint.
638 // We only treat this specially so we can do the non-negative check.
639 // TODO: maybe this wasn't worth it?
640 jint i = va_arg(ap, jint);
641 StringAppendF(&msg, "%d", i);
642 } else if (ch == 'm') { // jmethodID
643 jmethodID mid = va_arg(ap, jmethodID);
644 Method* m = reinterpret_cast<Method*>(Thread::Current()->DecodeJObject(reinterpret_cast<jweak>(mid)));
645 msg += PrettyMethod(m);
646 if (!entry) {
647 StringAppendF(&msg, " (%p)", mid);
648 }
649 } else if (ch == 'p') { // void* ("pointer")
650 void* p = va_arg(ap, void*);
651 if (p == NULL) {
652 msg += "NULL";
653 } else {
654 StringAppendF(&msg, "(void*) %p", p);
655 }
656 } else if (ch == 'r') { // jint (release mode)
657 jint releaseMode = va_arg(ap, jint);
658 if (releaseMode == 0) {
659 msg += "0";
660 } else if (releaseMode == JNI_ABORT) {
661 msg += "JNI_ABORT";
662 } else if (releaseMode == JNI_COMMIT) {
663 msg += "JNI_COMMIT";
664 } else {
665 StringAppendF(&msg, "invalid release mode %d", releaseMode);
666 }
667 } else if (ch == 'u') { // const char* (modified UTF-8)
668 const char* utf = va_arg(ap, const char*);
669 if (utf == NULL) {
670 msg += "NULL";
671 } else {
672 StringAppendF(&msg, "\"%s\"", utf);
673 }
674 } else if (ch == '.') {
675 msg += "...";
676 } else {
677 LOG(ERROR) << "unknown trace format specifier: " << ch;
678 JniAbort();
679 return;
680 }
681 if (*fmt) {
682 StringAppendF(&msg, ", ");
683 }
684 }
685 va_end(ap);
686
687 if (entry) {
688 if (mHasMethod) {
689 std::string methodName(PrettyMethod(method, false));
690 LOG(INFO) << "JNI: " << methodName << " -> " << mFunctionName << "(" << msg << ")";
691 mIndent = methodName.size() + 1;
692 } else {
693 LOG(INFO) << "JNI: -> " << mFunctionName << "(" << msg << ")";
694 mIndent = 0;
695 }
696 } else {
697 LOG(INFO) << StringPrintf("JNI: %*s<- %s returned %s", mIndent, "", mFunctionName, msg.c_str());
698 }
699 }
700
701 // We always do the thorough checks on entry, and never on exit...
702 if (entry) {
703 va_start(ap, fmt0);
704 for (const char* fmt = fmt0; *fmt; ++fmt) {
705 char ch = *fmt;
706 if (ch == 'a') {
707 checkArray(va_arg(ap, jarray));
708 } else if (ch == 'c') {
709 checkInstance(kClass, va_arg(ap, jclass));
710 } else if (ch == 'L') {
711 checkObject(va_arg(ap, jobject));
712 } else if (ch == 'r') {
713 checkReleaseMode(va_arg(ap, jint));
714 } else if (ch == 's') {
715 checkInstance(kString, va_arg(ap, jstring));
716 } else if (ch == 'u') {
717 if ((mFlags & kFlag_Release) != 0) {
718 checkNonNull(va_arg(ap, const char*));
719 } else {
720 bool nullable = ((mFlags & kFlag_NullableUtf) != 0);
721 checkUtfString(va_arg(ap, const char*), nullable);
722 }
723 } else if (ch == 'z') {
724 checkLengthPositive(va_arg(ap, jsize));
725 } else if (strchr("BCISZbfmpEv", ch) != NULL) {
726 va_arg(ap, int); // Skip this argument.
727 } else if (ch == 'D' || ch == 'F') {
728 va_arg(ap, double); // Skip this argument.
729 } else if (ch == 'J') {
730 va_arg(ap, long); // Skip this argument.
731 } else if (ch == '.') {
732 } else {
733 LOG(FATAL) << "unknown check format specifier: " << ch;
734 }
735 }
736 va_end(ap);
737 }
738 }
739
740private:
741 Field* DecodeField(ScopedJniThreadState& ts, jfieldID fid) {
742 return Decode<Field*>(ts, reinterpret_cast<jweak>(fid));
743 }
744
745 Method* DecodeMethod(ScopedJniThreadState& ts, jmethodID mid) {
746 return Decode<Method*>(ts, reinterpret_cast<jweak>(mid));
747 }
748
749 void init(JNIEnv* env, int flags, const char* functionName, bool hasMethod) {
750 mEnv = reinterpret_cast<JNIEnvExt*>(env);
751 mFlags = flags;
752 mFunctionName = functionName;
753
754 // Set "hasMethod" to true if we have a valid thread with a method pointer.
755 // We won't have one before attaching a thread, after detaching a thread, or
756 // after destroying the VM.
757 mHasMethod = hasMethod;
758 }
759
760 /*
761 * Verify that "array" is non-NULL and points to an Array object.
762 *
763 * Since we're dealing with objects, switch to "running" mode.
764 */
765 void checkArray(jarray java_array) {
766 if (java_array == NULL) {
767 LOG(ERROR) << "JNI ERROR: received null array";
768 JniAbort();
769 return;
770 }
771
772 ScopedJniThreadState ts(mEnv);
773 Array* a = Decode<Array*>(ts, java_array);
774 if (!Heap::IsHeapAddress(a)) {
775 LOG(ERROR) << "JNI ERROR: jarray is an invalid " << GetIndirectRefKind(java_array) << ": " << reinterpret_cast<void*>(java_array);
776 JniAbort();
777 } else if (!a->IsArrayInstance()) {
778 LOG(ERROR) << "JNI ERROR: jarray argument has non-array type: " << PrettyType(a);
779 JniAbort();
780 }
781 }
782
783 void checkLengthPositive(jsize length) {
784 if (length < 0) {
785 LOG(ERROR) << "JNI ERROR: negative jsize: " << length;
786 JniAbort();
787 }
788 }
789
790 /*
791 * Verify that "jobj" is a valid object, and that it's an object that JNI
792 * is allowed to know about. We allow NULL references.
793 *
794 * Switches to "running" mode before performing checks.
795 */
796 void checkObject(jobject java_object) {
797 if (java_object == NULL) {
798 return;
799 }
800
801 ScopedJniThreadState ts(mEnv);
802
803 Object* o = Decode<Object*>(ts, java_object);
804 if (o != NULL && !Heap::IsHeapAddress(o)) {
805 // TODO: when we remove workAroundAppJniBugs, this should be impossible.
806 LOG(ERROR) << "JNI ERROR: native code passing in reference to invalid " << GetIndirectRefKind(java_object) << ": " << java_object;
807 JniAbort();
808 }
809 }
810
811 /*
812 * Verify that the "mode" argument passed to a primitive array Release
813 * function is one of the valid values.
814 */
815 void checkReleaseMode(jint mode) {
816 if (mode != 0 && mode != JNI_COMMIT && mode != JNI_ABORT) {
817 LOG(ERROR) << "JNI ERROR: bad value for release mode: " << mode;
818 JniAbort();
819 }
820 }
821
822 void checkThread(int flags) {
823 Thread* self = Thread::Current();
824 if (self == NULL) {
825 LOG(ERROR) << "JNI ERROR: non-VM thread making JNI calls";
826 JniAbort();
827 return;
828 }
829
830 // Get the *correct* JNIEnv by going through our TLS pointer.
831 JNIEnvExt* threadEnv = self->GetJniEnv();
832
833 /*
834 * Verify that the current thread is (a) attached and (b) associated with
835 * this particular instance of JNIEnv.
836 */
837 if (mEnv != threadEnv) {
838 LOG(ERROR) << "JNI ERROR: thread " << *self << " using JNIEnv* from thread " << *mEnv->self;
839 // If we're keeping broken code limping along, we need to suppress the abort...
840 if (true/* TODO: !gDvmJni.workAroundAppJniBugs*/) {
841 JniAbort();
842 return;
843 }
844 }
845
846 /*
847 * Verify that, if this thread previously made a critical "get" call, we
848 * do the corresponding "release" call before we try anything else.
849 */
850 switch (flags & kFlag_CritMask) {
851 case kFlag_CritOkay: // okay to call this method
852 break;
853 case kFlag_CritBad: // not okay to call
854 if (threadEnv->critical) {
855 LOG(ERROR) << "JNI ERROR: thread " << *self << " using JNI after critical get";
856 JniAbort();
857 return;
858 }
859 break;
860 case kFlag_CritGet: // this is a "get" call
861 /* don't check here; we allow nested gets */
862 threadEnv->critical++;
863 break;
864 case kFlag_CritRelease: // this is a "release" call
865 threadEnv->critical--;
866 if (threadEnv->critical < 0) {
867 LOG(ERROR) << "JNI ERROR: thread " << *self << " called too many critical releases";
868 JniAbort();
869 return;
870 }
871 break;
872 default:
873 LOG(FATAL) << "bad flags (internal error): " << flags;
874 }
875
876 /*
877 * Verify that, if an exception has been raised, the native code doesn't
878 * make any JNI calls other than the Exception* methods.
879 */
880 if ((flags & kFlag_ExcepOkay) == 0 && self->IsExceptionPending()) {
881 LOG(ERROR) << "JNI ERROR: JNI method called with exception pending";
882 LOG(ERROR) << "Pending exception is: TODO"; // TODO
883 // TODO: dvmLogExceptionStackTrace();
884 JniAbort();
885 return;
886 }
887 }
888
889 /*
890 * Verify that "bytes" points to valid "modified UTF-8" data.
891 */
892 void checkUtfString(const char* bytes, bool nullable) {
893 if (bytes == NULL) {
894 if (!nullable) {
895 LOG(ERROR) << "JNI ERROR: non-nullable const char* was NULL";
896 JniAbort();
897 return;
898 }
899 return;
900 }
901
902 const char* errorKind = NULL;
903 uint8_t utf8 = checkUtfBytes(bytes, &errorKind);
904 if (errorKind != NULL) {
905 LOG(ERROR) << "JNI ERROR: input is not valid UTF-8: illegal " << errorKind << " byte " << StringPrintf("%#x", utf8);
906 LOG(ERROR) << " string: '" << bytes << "'";
907 JniAbort();
908 return;
909 }
910 }
911
912 enum InstanceKind {
913 kClass,
914 kDirectByteBuffer,
915 kString,
916 kThrowable,
917 };
918
919 /*
920 * Verify that "jobj" is a valid non-NULL object reference, and points to
921 * an instance of expectedClass.
922 *
923 * Because we're looking at an object on the GC heap, we have to switch
924 * to "running" mode before doing the checks.
925 */
926 void checkInstance(InstanceKind kind, jobject java_object) {
927 const char* what;
928 switch (kind) {
929 case kClass:
930 what = "jclass";
931 break;
932 case kDirectByteBuffer:
933 what = "direct ByteBuffer";
934 break;
935 case kString:
936 what = "jstring";
937 break;
938 case kThrowable:
939 what = "jthrowable";
940 break;
941 default:
942 CHECK(false) << static_cast<int>(kind);
943 }
944
945 if (java_object == NULL) {
946 LOG(ERROR) << "JNI ERROR: received null " << what;
947 JniAbort();
948 return;
949 }
950
951 ScopedJniThreadState ts(mEnv);
952 Object* obj = Decode<Object*>(ts, java_object);
953 if (!Heap::IsHeapAddress(obj)) {
954 LOG(ERROR) << "JNI ERROR: " << what << " is an invalid " << GetIndirectRefKind(java_object) << ": " << java_object;
955 JniAbort();
956 return;
957 }
958
959 bool okay = true;
960 switch (kind) {
961 case kClass:
962 okay = obj->IsClass();
963 break;
964 case kDirectByteBuffer:
965 // TODO
966 break;
967 case kString:
968 okay = obj->IsString();
969 break;
970 case kThrowable:
971 // TODO
972 break;
973 }
974 if (!okay) {
975 LOG(ERROR) << "JNI ERROR: " << what << " has wrong type: " << PrettyType(obj);
976 JniAbort();
977 }
978 }
979
980 static uint8_t checkUtfBytes(const char* bytes, const char** errorKind) {
981 while (*bytes != '\0') {
982 uint8_t utf8 = *(bytes++);
983 // Switch on the high four bits.
984 switch (utf8 >> 4) {
985 case 0x00:
986 case 0x01:
987 case 0x02:
988 case 0x03:
989 case 0x04:
990 case 0x05:
991 case 0x06:
992 case 0x07:
993 // Bit pattern 0xxx. No need for any extra bytes.
994 break;
995 case 0x08:
996 case 0x09:
997 case 0x0a:
998 case 0x0b:
999 case 0x0f:
1000 /*
1001 * Bit pattern 10xx or 1111, which are illegal start bytes.
1002 * Note: 1111 is valid for normal UTF-8, but not the
1003 * modified UTF-8 used here.
1004 */
1005 *errorKind = "start";
1006 return utf8;
1007 case 0x0e:
1008 // Bit pattern 1110, so there are two additional bytes.
1009 utf8 = *(bytes++);
1010 if ((utf8 & 0xc0) != 0x80) {
1011 *errorKind = "continuation";
1012 return utf8;
1013 }
1014 // Fall through to take care of the final byte.
1015 case 0x0c:
1016 case 0x0d:
1017 // Bit pattern 110x, so there is one additional byte.
1018 utf8 = *(bytes++);
1019 if ((utf8 & 0xc0) != 0x80) {
1020 *errorKind = "continuation";
1021 return utf8;
1022 }
1023 break;
1024 }
1025 }
1026 return 0;
1027 }
1028
1029 void JniAbort() {
1030 ::art::JniAbort(mFunctionName);
1031 }
1032
1033 JNIEnvExt* mEnv;
1034 const char* mFunctionName;
1035 int mFlags;
1036 bool mHasMethod;
1037 size_t mIndent;
1038
1039 DISALLOW_COPY_AND_ASSIGN(ScopedCheck);
1040};
1041
1042#define CHECK_JNI_ENTRY(flags, types, args...) \
1043 ScopedCheck sc(env, flags, __FUNCTION__); \
1044 sc.check(true, types, ##args)
1045
1046#define CHECK_JNI_EXIT(type, exp) ({ \
1047 typeof (exp) _rc = (exp); \
1048 sc.check(false, type, _rc); \
1049 _rc; })
1050#define CHECK_JNI_EXIT_VOID() \
1051 sc.check(false, "V")
1052
1053/*
1054 * ===========================================================================
1055 * Guarded arrays
1056 * ===========================================================================
1057 */
1058
1059#define kGuardLen 512 /* must be multiple of 2 */
1060#define kGuardPattern 0xd5e3 /* uncommon values; d5e3d5e3 invalid addr */
1061#define kGuardMagic 0xffd5aa96
1062
1063/* this gets tucked in at the start of the buffer; struct size must be even */
1064struct GuardedCopy {
1065 uint32_t magic;
1066 uLong adler;
1067 size_t originalLen;
1068 const void* originalPtr;
1069
1070 /* find the GuardedCopy given the pointer into the "live" data */
1071 static inline const GuardedCopy* fromData(const void* dataBuf) {
1072 return reinterpret_cast<const GuardedCopy*>(actualBuffer(dataBuf));
1073 }
1074
1075 /*
1076 * Create an over-sized buffer to hold the contents of "buf". Copy it in,
1077 * filling in the area around it with guard data.
1078 *
1079 * We use a 16-bit pattern to make a rogue memset less likely to elude us.
1080 */
1081 static void* create(const void* buf, size_t len, bool modOkay) {
1082 size_t newLen = actualLength(len);
1083 uint8_t* newBuf = debugAlloc(newLen);
1084
1085 /* fill it in with a pattern */
1086 uint16_t* pat = (uint16_t*) newBuf;
1087 for (size_t i = 0; i < newLen / 2; i++) {
1088 *pat++ = kGuardPattern;
1089 }
1090
1091 /* copy the data in; note "len" could be zero */
1092 memcpy(newBuf + kGuardLen / 2, buf, len);
1093
1094 /* if modification is not expected, grab a checksum */
1095 uLong adler = 0;
1096 if (!modOkay) {
1097 adler = adler32(0L, Z_NULL, 0);
1098 adler = adler32(adler, (const Bytef*)buf, len);
1099 *(uLong*)newBuf = adler;
1100 }
1101
1102 GuardedCopy* pExtra = reinterpret_cast<GuardedCopy*>(newBuf);
1103 pExtra->magic = kGuardMagic;
1104 pExtra->adler = adler;
1105 pExtra->originalPtr = buf;
1106 pExtra->originalLen = len;
1107
1108 return newBuf + kGuardLen / 2;
1109 }
1110
1111 /*
1112 * Free up the guard buffer, scrub it, and return the original pointer.
1113 */
1114 static void* destroy(void* dataBuf) {
1115 const GuardedCopy* pExtra = GuardedCopy::fromData(dataBuf);
1116 void* originalPtr = (void*) pExtra->originalPtr;
1117 size_t len = pExtra->originalLen;
1118 debugFree(dataBuf, len);
1119 return originalPtr;
1120 }
1121
1122 /*
1123 * Verify the guard area and, if "modOkay" is false, that the data itself
1124 * has not been altered.
1125 *
1126 * The caller has already checked that "dataBuf" is non-NULL.
1127 */
1128 static void check(const char* functionName, const void* dataBuf, bool modOkay) {
1129 static const uint32_t kMagicCmp = kGuardMagic;
1130 const uint8_t* fullBuf = actualBuffer(dataBuf);
1131 const GuardedCopy* pExtra = GuardedCopy::fromData(dataBuf);
1132
1133 /*
1134 * Before we do anything with "pExtra", check the magic number. We
1135 * do the check with memcmp rather than "==" in case the pointer is
1136 * unaligned. If it points to completely bogus memory we're going
1137 * to crash, but there's no easy way around that.
1138 */
1139 if (memcmp(&pExtra->magic, &kMagicCmp, 4) != 0) {
1140 uint8_t buf[4];
1141 memcpy(buf, &pExtra->magic, 4);
1142 LOG(ERROR) << StringPrintf("JNI: guard magic does not match "
1143 "(found 0x%02x%02x%02x%02x) -- incorrect data pointer %p?",
1144 buf[3], buf[2], buf[1], buf[0], dataBuf); /* assume little endian */
1145 JniAbort(functionName);
1146 }
1147
1148 size_t len = pExtra->originalLen;
1149
1150 /* check bottom half of guard; skip over optional checksum storage */
1151 const uint16_t* pat = (uint16_t*) fullBuf;
1152 for (size_t i = sizeof(GuardedCopy) / 2; i < (kGuardLen / 2 - sizeof(GuardedCopy)) / 2; i++) {
1153 if (pat[i] != kGuardPattern) {
1154 LOG(ERROR) << "JNI: guard pattern(1) disturbed at " << (void*) fullBuf << " + " << (i*2);
1155 JniAbort(functionName);
1156 }
1157 }
1158
1159 int offset = kGuardLen / 2 + len;
1160 if (offset & 0x01) {
1161 /* odd byte; expected value depends on endian-ness of host */
1162 const uint16_t patSample = kGuardPattern;
1163 if (fullBuf[offset] != ((const uint8_t*) &patSample)[1]) {
1164 LOG(ERROR) << "JNI: guard pattern disturbed in odd byte after "
1165 << (void*) fullBuf << " (+" << offset << ") "
1166 << StringPrintf("0x%02x 0x%02x", fullBuf[offset], ((const uint8_t*) &patSample)[1]);
1167 JniAbort(functionName);
1168 }
1169 offset++;
1170 }
1171
1172 /* check top half of guard */
1173 pat = (uint16_t*) (fullBuf + offset);
1174 for (size_t i = 0; i < kGuardLen / 4; i++) {
1175 if (pat[i] != kGuardPattern) {
1176 LOG(ERROR) << "JNI: guard pattern(2) disturbed at " << (void*) fullBuf << " + " << (offset + i*2);
1177 JniAbort(functionName);
1178 }
1179 }
1180
1181 /*
1182 * If modification is not expected, verify checksum. Strictly speaking
1183 * this is wrong: if we told the client that we made a copy, there's no
1184 * reason they can't alter the buffer.
1185 */
1186 if (!modOkay) {
1187 uLong adler = adler32(0L, Z_NULL, 0);
1188 adler = adler32(adler, (const Bytef*)dataBuf, len);
1189 if (pExtra->adler != adler) {
1190 LOG(ERROR) << StringPrintf("JNI: buffer modified (0x%08lx vs 0x%08lx) at addr %p", pExtra->adler, adler, dataBuf);
1191 JniAbort(functionName);
1192 }
1193 }
1194 }
1195
1196 private:
1197 static uint8_t* debugAlloc(size_t len) {
1198 void* result = mmap(NULL, len, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON, -1, 0);
1199 if (result == MAP_FAILED) {
1200 PLOG(FATAL) << "GuardedCopy::create mmap(" << len << ") failed";
1201 }
1202 return reinterpret_cast<uint8_t*>(result);
1203 }
1204
1205 static void debugFree(void* dataBuf, size_t len) {
1206 uint8_t* fullBuf = actualBuffer(dataBuf);
1207 size_t totalByteCount = actualLength(len);
1208 // TODO: we could mprotect instead, and keep the allocation around for a while.
1209 // This would be even more expensive, but it might catch more errors.
1210 // if (mprotect(fullBuf, totalByteCount, PROT_NONE) != 0) {
1211 // LOGW("mprotect(PROT_NONE) failed: %s", strerror(errno));
1212 // }
1213 if (munmap(fullBuf, totalByteCount) != 0) {
1214 PLOG(FATAL) << "munmap(" << (void*) fullBuf << ", " << totalByteCount << ") failed";
1215 }
1216 }
1217
1218 static const uint8_t* actualBuffer(const void* dataBuf) {
1219 return reinterpret_cast<const uint8_t*>(dataBuf) - kGuardLen / 2;
1220 }
1221
1222 static uint8_t* actualBuffer(void* dataBuf) {
1223 return reinterpret_cast<uint8_t*>(dataBuf) - kGuardLen / 2;
1224 }
1225
1226 // Underlying length of a user allocation of 'length' bytes.
1227 static size_t actualLength(size_t length) {
1228 return (length + kGuardLen + 1) & ~0x01;
1229 }
1230};
1231
1232/*
1233 * Create a guarded copy of a primitive array. Modifications to the copied
1234 * data are allowed. Returns a pointer to the copied data.
1235 */
1236void* CreateGuardedPACopy(JNIEnv* env, const jarray java_array, jboolean* isCopy) {
1237 ScopedJniThreadState ts(env);
1238
1239 Array* a = Decode<Array*>(ts, java_array);
1240 size_t byte_count = a->GetLength() * a->GetClass()->GetComponentSize();
1241 void* result = GuardedCopy::create(reinterpret_cast<ByteArray*>(a)->GetData(), byte_count, true);
1242 if (isCopy != NULL) {
1243 *isCopy = JNI_TRUE;
1244 }
1245 return result;
1246}
1247
1248/*
1249 * Perform the array "release" operation, which may or may not copy data
1250 * back into the VM, and may or may not release the underlying storage.
1251 */
1252void ReleaseGuardedPACopy(JNIEnv* env, jarray java_array, void* dataBuf, int mode) {
1253 if (reinterpret_cast<uintptr_t>(dataBuf) == kNoCopyMagic) {
1254 return;
1255 }
1256
1257 ScopedJniThreadState ts(env);
1258 Array* a = Decode<Array*>(ts, java_array);
1259
1260 GuardedCopy::check(__FUNCTION__, dataBuf, true);
1261
1262 if (mode != JNI_ABORT) {
1263 size_t len = GuardedCopy::fromData(dataBuf)->originalLen;
1264 memcpy(reinterpret_cast<ByteArray*>(a)->GetData(), dataBuf, len);
1265 }
1266 if (mode != JNI_COMMIT) {
1267 GuardedCopy::destroy(dataBuf);
1268 }
1269}
1270
1271/*
1272 * ===========================================================================
1273 * JNI functions
1274 * ===========================================================================
1275 */
1276
1277class CheckJNI {
1278 public:
1279 static jint GetVersion(JNIEnv* env) {
1280 CHECK_JNI_ENTRY(kFlag_Default, "E", env);
1281 return CHECK_JNI_EXIT("I", baseEnv(env)->GetVersion(env));
1282 }
1283
1284 static jclass DefineClass(JNIEnv* env, const char* name, jobject loader, const jbyte* buf, jsize bufLen) {
1285 CHECK_JNI_ENTRY(kFlag_Default, "EuLpz", env, name, loader, buf, bufLen);
1286 sc.checkClassName(name);
1287 return CHECK_JNI_EXIT("c", baseEnv(env)->DefineClass(env, name, loader, buf, bufLen));
1288 }
1289
1290 static jclass FindClass(JNIEnv* env, const char* name) {
1291 CHECK_JNI_ENTRY(kFlag_Default, "Eu", env, name);
1292 sc.checkClassName(name);
1293 return CHECK_JNI_EXIT("c", baseEnv(env)->FindClass(env, name));
1294 }
1295
1296 static jclass GetSuperclass(JNIEnv* env, jclass clazz) {
1297 CHECK_JNI_ENTRY(kFlag_Default, "Ec", env, clazz);
1298 return CHECK_JNI_EXIT("c", baseEnv(env)->GetSuperclass(env, clazz));
1299 }
1300
1301 static jboolean IsAssignableFrom(JNIEnv* env, jclass clazz1, jclass clazz2) {
1302 CHECK_JNI_ENTRY(kFlag_Default, "Ecc", env, clazz1, clazz2);
1303 return CHECK_JNI_EXIT("b", baseEnv(env)->IsAssignableFrom(env, clazz1, clazz2));
1304 }
1305
1306 static jmethodID FromReflectedMethod(JNIEnv* env, jobject method) {
1307 CHECK_JNI_ENTRY(kFlag_Default, "EL", env, method);
1308 // TODO: check that 'field' is a java.lang.reflect.Method.
1309 return CHECK_JNI_EXIT("m", baseEnv(env)->FromReflectedMethod(env, method));
1310 }
1311
1312 static jfieldID FromReflectedField(JNIEnv* env, jobject field) {
1313 CHECK_JNI_ENTRY(kFlag_Default, "EL", env, field);
1314 // TODO: check that 'field' is a java.lang.reflect.Field.
1315 return CHECK_JNI_EXIT("f", baseEnv(env)->FromReflectedField(env, field));
1316 }
1317
1318 static jobject ToReflectedMethod(JNIEnv* env, jclass cls, jmethodID mid, jboolean isStatic) {
1319 CHECK_JNI_ENTRY(kFlag_Default, "Ecmb", env, cls, mid, isStatic);
1320 return CHECK_JNI_EXIT("L", baseEnv(env)->ToReflectedMethod(env, cls, mid, isStatic));
1321 }
1322
1323 static jobject ToReflectedField(JNIEnv* env, jclass cls, jfieldID fid, jboolean isStatic) {
1324 CHECK_JNI_ENTRY(kFlag_Default, "Ecfb", env, cls, fid, isStatic);
1325 return CHECK_JNI_EXIT("L", baseEnv(env)->ToReflectedField(env, cls, fid, isStatic));
1326 }
1327
1328 static jint Throw(JNIEnv* env, jthrowable obj) {
1329 CHECK_JNI_ENTRY(kFlag_Default, "EL", env, obj);
1330 // TODO: check that 'obj' is a java.lang.Throwable.
1331 return CHECK_JNI_EXIT("I", baseEnv(env)->Throw(env, obj));
1332 }
1333
1334 static jint ThrowNew(JNIEnv* env, jclass clazz, const char* message) {
1335 CHECK_JNI_ENTRY(kFlag_NullableUtf, "Ecu", env, clazz, message);
1336 return CHECK_JNI_EXIT("I", baseEnv(env)->ThrowNew(env, clazz, message));
1337 }
1338
1339 static jthrowable ExceptionOccurred(JNIEnv* env) {
1340 CHECK_JNI_ENTRY(kFlag_ExcepOkay, "E", env);
1341 return CHECK_JNI_EXIT("L", baseEnv(env)->ExceptionOccurred(env));
1342 }
1343
1344 static void ExceptionDescribe(JNIEnv* env) {
1345 CHECK_JNI_ENTRY(kFlag_ExcepOkay, "E", env);
1346 baseEnv(env)->ExceptionDescribe(env);
1347 CHECK_JNI_EXIT_VOID();
1348 }
1349
1350 static void ExceptionClear(JNIEnv* env) {
1351 CHECK_JNI_ENTRY(kFlag_ExcepOkay, "E", env);
1352 baseEnv(env)->ExceptionClear(env);
1353 CHECK_JNI_EXIT_VOID();
1354 }
1355
1356 static void FatalError(JNIEnv* env, const char* msg) {
1357 CHECK_JNI_ENTRY(kFlag_NullableUtf, "Eu", env, msg);
1358 baseEnv(env)->FatalError(env, msg);
1359 CHECK_JNI_EXIT_VOID();
1360 }
1361
1362 static jint PushLocalFrame(JNIEnv* env, jint capacity) {
1363 CHECK_JNI_ENTRY(kFlag_Default | kFlag_ExcepOkay, "EI", env, capacity);
1364 return CHECK_JNI_EXIT("I", baseEnv(env)->PushLocalFrame(env, capacity));
1365 }
1366
1367 static jobject PopLocalFrame(JNIEnv* env, jobject res) {
1368 CHECK_JNI_ENTRY(kFlag_Default | kFlag_ExcepOkay, "EL", env, res);
1369 return CHECK_JNI_EXIT("L", baseEnv(env)->PopLocalFrame(env, res));
1370 }
1371
1372 static jobject NewGlobalRef(JNIEnv* env, jobject obj) {
1373 CHECK_JNI_ENTRY(kFlag_Default, "EL", env, obj);
1374 return CHECK_JNI_EXIT("L", baseEnv(env)->NewGlobalRef(env, obj));
1375 }
1376
1377 static jobject NewLocalRef(JNIEnv* env, jobject ref) {
1378 CHECK_JNI_ENTRY(kFlag_Default, "EL", env, ref);
1379 return CHECK_JNI_EXIT("L", baseEnv(env)->NewLocalRef(env, ref));
1380 }
1381
1382 static void DeleteGlobalRef(JNIEnv* env, jobject globalRef) {
1383 CHECK_JNI_ENTRY(kFlag_Default | kFlag_ExcepOkay, "EL", env, globalRef);
1384 if (globalRef != NULL && GetIndirectRefKind(globalRef) != kGlobal) {
1385 LOG(ERROR) << "JNI ERROR: DeleteGlobalRef on " << GetIndirectRefKind(globalRef) << ": " << globalRef;
1386 JniAbort(__FUNCTION__);
1387 } else {
1388 baseEnv(env)->DeleteGlobalRef(env, globalRef);
1389 CHECK_JNI_EXIT_VOID();
1390 }
1391 }
1392
1393 static void DeleteWeakGlobalRef(JNIEnv* env, jweak weakGlobalRef) {
1394 CHECK_JNI_ENTRY(kFlag_Default | kFlag_ExcepOkay, "EL", env, weakGlobalRef);
1395 if (weakGlobalRef != NULL && GetIndirectRefKind(weakGlobalRef) != kWeakGlobal) {
1396 LOG(ERROR) << "JNI ERROR: DeleteWeakGlobalRef on " << GetIndirectRefKind(weakGlobalRef) << ": " << weakGlobalRef;
1397 JniAbort(__FUNCTION__);
1398 } else {
1399 baseEnv(env)->DeleteWeakGlobalRef(env, weakGlobalRef);
1400 CHECK_JNI_EXIT_VOID();
1401 }
1402 }
1403
1404 static void DeleteLocalRef(JNIEnv* env, jobject localRef) {
1405 CHECK_JNI_ENTRY(kFlag_Default | kFlag_ExcepOkay, "EL", env, localRef);
1406 if (localRef != NULL && GetIndirectRefKind(localRef) != kLocal) {
1407 LOG(ERROR) << "JNI ERROR: DeleteLocalRef on " << GetIndirectRefKind(localRef) << ": " << localRef;
1408 JniAbort(__FUNCTION__);
1409 } else {
1410 baseEnv(env)->DeleteLocalRef(env, localRef);
1411 CHECK_JNI_EXIT_VOID();
1412 }
1413 }
1414
1415 static jint EnsureLocalCapacity(JNIEnv *env, jint capacity) {
1416 CHECK_JNI_ENTRY(kFlag_Default, "EI", env, capacity);
1417 return CHECK_JNI_EXIT("I", baseEnv(env)->EnsureLocalCapacity(env, capacity));
1418 }
1419
1420 static jboolean IsSameObject(JNIEnv* env, jobject ref1, jobject ref2) {
1421 CHECK_JNI_ENTRY(kFlag_Default, "ELL", env, ref1, ref2);
1422 return CHECK_JNI_EXIT("b", baseEnv(env)->IsSameObject(env, ref1, ref2));
1423 }
1424
1425 static jobject AllocObject(JNIEnv* env, jclass clazz) {
1426 CHECK_JNI_ENTRY(kFlag_Default, "Ec", env, clazz);
1427 return CHECK_JNI_EXIT("L", baseEnv(env)->AllocObject(env, clazz));
1428 }
1429
1430 static jobject NewObject(JNIEnv* env, jclass clazz, jmethodID mid, ...) {
1431 CHECK_JNI_ENTRY(kFlag_Default, "Ecm.", env, clazz, mid);
1432 va_list args;
1433 va_start(args, mid);
1434 jobject result = baseEnv(env)->NewObjectV(env, clazz, mid, args);
1435 va_end(args);
1436 return CHECK_JNI_EXIT("L", result);
1437 }
1438
1439 static jobject NewObjectV(JNIEnv* env, jclass clazz, jmethodID mid, va_list args) {
1440 CHECK_JNI_ENTRY(kFlag_Default, "Ecm.", env, clazz, mid);
1441 return CHECK_JNI_EXIT("L", baseEnv(env)->NewObjectV(env, clazz, mid, args));
1442 }
1443
1444 static jobject NewObjectA(JNIEnv* env, jclass clazz, jmethodID mid, jvalue* args) {
1445 CHECK_JNI_ENTRY(kFlag_Default, "Ecm.", env, clazz, mid);
1446 return CHECK_JNI_EXIT("L", baseEnv(env)->NewObjectA(env, clazz, mid, args));
1447 }
1448
1449 static jclass GetObjectClass(JNIEnv* env, jobject obj) {
1450 CHECK_JNI_ENTRY(kFlag_Default, "EL", env, obj);
1451 return CHECK_JNI_EXIT("c", baseEnv(env)->GetObjectClass(env, obj));
1452 }
1453
1454 static jboolean IsInstanceOf(JNIEnv* env, jobject obj, jclass clazz) {
1455 CHECK_JNI_ENTRY(kFlag_Default, "ELc", env, obj, clazz);
1456 return CHECK_JNI_EXIT("b", baseEnv(env)->IsInstanceOf(env, obj, clazz));
1457 }
1458
1459 static jmethodID GetMethodID(JNIEnv* env, jclass clazz, const char* name, const char* sig) {
1460 CHECK_JNI_ENTRY(kFlag_Default, "Ecuu", env, clazz, name, sig);
1461 return CHECK_JNI_EXIT("m", baseEnv(env)->GetMethodID(env, clazz, name, sig));
1462 }
1463
1464 static jfieldID GetFieldID(JNIEnv* env, jclass clazz, const char* name, const char* sig) {
1465 CHECK_JNI_ENTRY(kFlag_Default, "Ecuu", env, clazz, name, sig);
1466 return CHECK_JNI_EXIT("f", baseEnv(env)->GetFieldID(env, clazz, name, sig));
1467 }
1468
1469 static jmethodID GetStaticMethodID(JNIEnv* env, jclass clazz, const char* name, const char* sig) {
1470 CHECK_JNI_ENTRY(kFlag_Default, "Ecuu", env, clazz, name, sig);
1471 return CHECK_JNI_EXIT("m", baseEnv(env)->GetStaticMethodID(env, clazz, name, sig));
1472 }
1473
1474 static jfieldID GetStaticFieldID(JNIEnv* env, jclass clazz, const char* name, const char* sig) {
1475 CHECK_JNI_ENTRY(kFlag_Default, "Ecuu", env, clazz, name, sig);
1476 return CHECK_JNI_EXIT("f", baseEnv(env)->GetStaticFieldID(env, clazz, name, sig));
1477 }
1478
1479#define FIELD_ACCESSORS(_ctype, _jname, _type) \
1480 static _ctype GetStatic##_jname##Field(JNIEnv* env, jclass clazz, jfieldID fid) { \
1481 CHECK_JNI_ENTRY(kFlag_Default, "Ecf", env, clazz, fid); \
1482 sc.checkStaticFieldID(clazz, fid); \
1483 return CHECK_JNI_EXIT(_type, baseEnv(env)->GetStatic##_jname##Field(env, clazz, fid)); \
1484 } \
1485 static _ctype Get##_jname##Field(JNIEnv* env, jobject obj, jfieldID fid) { \
1486 CHECK_JNI_ENTRY(kFlag_Default, "ELf", env, obj, fid); \
1487 sc.checkInstanceFieldID(obj, fid); \
1488 return CHECK_JNI_EXIT(_type, baseEnv(env)->Get##_jname##Field(env, obj, fid)); \
1489 } \
1490 static void SetStatic##_jname##Field(JNIEnv* env, jclass clazz, jfieldID fid, _ctype value) { \
1491 CHECK_JNI_ENTRY(kFlag_Default, "Ecf" _type, env, clazz, fid, value); \
1492 sc.checkStaticFieldID(clazz, fid); \
1493 /* "value" arg only used when type == ref */ \
1494 sc.checkFieldType((jobject)(uint32_t)value, fid, _type[0], true); \
1495 baseEnv(env)->SetStatic##_jname##Field(env, clazz, fid, value); \
1496 CHECK_JNI_EXIT_VOID(); \
1497 } \
1498 static void Set##_jname##Field(JNIEnv* env, jobject obj, jfieldID fid, _ctype value) { \
1499 CHECK_JNI_ENTRY(kFlag_Default, "ELf" _type, env, obj, fid, value); \
1500 sc.checkInstanceFieldID(obj, fid); \
1501 /* "value" arg only used when type == ref */ \
1502 sc.checkFieldType((jobject)(uint32_t) value, fid, _type[0], false); \
1503 baseEnv(env)->Set##_jname##Field(env, obj, fid, value); \
1504 CHECK_JNI_EXIT_VOID(); \
1505 }
1506
1507FIELD_ACCESSORS(jobject, Object, "L");
1508FIELD_ACCESSORS(jboolean, Boolean, "Z");
1509FIELD_ACCESSORS(jbyte, Byte, "B");
1510FIELD_ACCESSORS(jchar, Char, "C");
1511FIELD_ACCESSORS(jshort, Short, "S");
1512FIELD_ACCESSORS(jint, Int, "I");
1513FIELD_ACCESSORS(jlong, Long, "J");
1514FIELD_ACCESSORS(jfloat, Float, "F");
1515FIELD_ACCESSORS(jdouble, Double, "D");
1516
1517#define CALL(_ctype, _jname, _retdecl, _retasgn, _retok, _retsig) \
1518 /* Virtual... */ \
1519 static _ctype Call##_jname##Method(JNIEnv* env, jobject obj, \
1520 jmethodID mid, ...) \
1521 { \
1522 CHECK_JNI_ENTRY(kFlag_Default, "ELm.", env, obj, mid); /* TODO: args! */ \
1523 sc.checkSig(mid, _retsig, false); \
1524 sc.checkVirtualMethod(obj, mid); \
1525 _retdecl; \
1526 va_list args; \
1527 va_start(args, mid); \
1528 _retasgn baseEnv(env)->Call##_jname##MethodV(env, obj, mid, args); \
1529 va_end(args); \
1530 _retok; \
1531 } \
1532 static _ctype Call##_jname##MethodV(JNIEnv* env, jobject obj, \
1533 jmethodID mid, va_list args) \
1534 { \
1535 CHECK_JNI_ENTRY(kFlag_Default, "ELm.", env, obj, mid); /* TODO: args! */ \
1536 sc.checkSig(mid, _retsig, false); \
1537 sc.checkVirtualMethod(obj, mid); \
1538 _retdecl; \
1539 _retasgn baseEnv(env)->Call##_jname##MethodV(env, obj, mid, args); \
1540 _retok; \
1541 } \
1542 static _ctype Call##_jname##MethodA(JNIEnv* env, jobject obj, \
1543 jmethodID mid, jvalue* args) \
1544 { \
1545 CHECK_JNI_ENTRY(kFlag_Default, "ELm.", env, obj, mid); /* TODO: args! */ \
1546 sc.checkSig(mid, _retsig, false); \
1547 sc.checkVirtualMethod(obj, mid); \
1548 _retdecl; \
1549 _retasgn baseEnv(env)->Call##_jname##MethodA(env, obj, mid, args); \
1550 _retok; \
1551 } \
1552 /* Non-virtual... */ \
1553 static _ctype CallNonvirtual##_jname##Method(JNIEnv* env, \
1554 jobject obj, jclass clazz, jmethodID mid, ...) \
1555 { \
1556 CHECK_JNI_ENTRY(kFlag_Default, "ELcm.", env, obj, clazz, mid); /* TODO: args! */ \
1557 sc.checkSig(mid, _retsig, false); \
1558 sc.checkVirtualMethod(obj, mid); \
1559 _retdecl; \
1560 va_list args; \
1561 va_start(args, mid); \
1562 _retasgn baseEnv(env)->CallNonvirtual##_jname##MethodV(env, obj, clazz, mid, args); \
1563 va_end(args); \
1564 _retok; \
1565 } \
1566 static _ctype CallNonvirtual##_jname##MethodV(JNIEnv* env, \
1567 jobject obj, jclass clazz, jmethodID mid, va_list args) \
1568 { \
1569 CHECK_JNI_ENTRY(kFlag_Default, "ELcm.", env, obj, clazz, mid); /* TODO: args! */ \
1570 sc.checkSig(mid, _retsig, false); \
1571 sc.checkVirtualMethod(obj, mid); \
1572 _retdecl; \
1573 _retasgn baseEnv(env)->CallNonvirtual##_jname##MethodV(env, obj, clazz, mid, args); \
1574 _retok; \
1575 } \
1576 static _ctype CallNonvirtual##_jname##MethodA(JNIEnv* env, \
1577 jobject obj, jclass clazz, jmethodID mid, jvalue* args) \
1578 { \
1579 CHECK_JNI_ENTRY(kFlag_Default, "ELcm.", env, obj, clazz, mid); /* TODO: args! */ \
1580 sc.checkSig(mid, _retsig, false); \
1581 sc.checkVirtualMethod(obj, mid); \
1582 _retdecl; \
1583 _retasgn baseEnv(env)->CallNonvirtual##_jname##MethodA(env, obj, clazz, mid, args); \
1584 _retok; \
1585 } \
1586 /* Static... */ \
1587 static _ctype CallStatic##_jname##Method(JNIEnv* env, \
1588 jclass clazz, jmethodID mid, ...) \
1589 { \
1590 CHECK_JNI_ENTRY(kFlag_Default, "Ecm.", env, clazz, mid); /* TODO: args! */ \
1591 sc.checkSig(mid, _retsig, true); \
1592 sc.checkStaticMethod(clazz, mid); \
1593 _retdecl; \
1594 va_list args; \
1595 va_start(args, mid); \
1596 _retasgn baseEnv(env)->CallStatic##_jname##MethodV(env, clazz, mid, args); \
1597 va_end(args); \
1598 _retok; \
1599 } \
1600 static _ctype CallStatic##_jname##MethodV(JNIEnv* env, \
1601 jclass clazz, jmethodID mid, va_list args) \
1602 { \
1603 CHECK_JNI_ENTRY(kFlag_Default, "Ecm.", env, clazz, mid); /* TODO: args! */ \
1604 sc.checkSig(mid, _retsig, true); \
1605 sc.checkStaticMethod(clazz, mid); \
1606 _retdecl; \
1607 _retasgn baseEnv(env)->CallStatic##_jname##MethodV(env, clazz, mid, args); \
1608 _retok; \
1609 } \
1610 static _ctype CallStatic##_jname##MethodA(JNIEnv* env, \
1611 jclass clazz, jmethodID mid, jvalue* args) \
1612 { \
1613 CHECK_JNI_ENTRY(kFlag_Default, "Ecm.", env, clazz, mid); /* TODO: args! */ \
1614 sc.checkSig(mid, _retsig, true); \
1615 sc.checkStaticMethod(clazz, mid); \
1616 _retdecl; \
1617 _retasgn baseEnv(env)->CallStatic##_jname##MethodA(env, clazz, mid, args); \
1618 _retok; \
1619 }
1620
1621#define NON_VOID_RETURN(_retsig, _ctype) return CHECK_JNI_EXIT(_retsig, (_ctype) result)
1622#define VOID_RETURN CHECK_JNI_EXIT_VOID()
1623
1624CALL(jobject, Object, Object* result, result=(Object*), NON_VOID_RETURN("L", jobject), "L");
1625CALL(jboolean, Boolean, jboolean result, result=, NON_VOID_RETURN("Z", jboolean), "Z");
1626CALL(jbyte, Byte, jbyte result, result=, NON_VOID_RETURN("B", jbyte), "B");
1627CALL(jchar, Char, jchar result, result=, NON_VOID_RETURN("C", jchar), "C");
1628CALL(jshort, Short, jshort result, result=, NON_VOID_RETURN("S", jshort), "S");
1629CALL(jint, Int, jint result, result=, NON_VOID_RETURN("I", jint), "I");
1630CALL(jlong, Long, jlong result, result=, NON_VOID_RETURN("J", jlong), "J");
1631CALL(jfloat, Float, jfloat result, result=, NON_VOID_RETURN("F", jfloat), "F");
1632CALL(jdouble, Double, jdouble result, result=, NON_VOID_RETURN("D", jdouble), "D");
1633CALL(void, Void, , , VOID_RETURN, "V");
1634
1635 static jstring NewString(JNIEnv* env, const jchar* unicodeChars, jsize len) {
1636 CHECK_JNI_ENTRY(kFlag_Default, "Epz", env, unicodeChars, len);
1637 return CHECK_JNI_EXIT("s", baseEnv(env)->NewString(env, unicodeChars, len));
1638 }
1639
1640 static jsize GetStringLength(JNIEnv* env, jstring string) {
1641 CHECK_JNI_ENTRY(kFlag_CritOkay, "Es", env, string);
1642 return CHECK_JNI_EXIT("I", baseEnv(env)->GetStringLength(env, string));
1643 }
1644
1645 static const jchar* GetStringChars(JNIEnv* env, jstring java_string, jboolean* isCopy) {
1646 CHECK_JNI_ENTRY(kFlag_CritOkay, "Esp", env, java_string, isCopy);
1647 const jchar* result = baseEnv(env)->GetStringChars(env, java_string, isCopy);
1648 if (sc.forceCopy() && result != NULL) {
1649 ScopedJniThreadState ts(env);
1650 String* s = Decode<String*>(ts, java_string);
1651 int byteCount = s->GetLength() * 2;
1652 result = (const jchar*) GuardedCopy::create(result, byteCount, false);
1653 if (isCopy != NULL) {
1654 *isCopy = JNI_TRUE;
1655 }
1656 }
1657 return CHECK_JNI_EXIT("p", result);
1658 }
1659
1660 static void ReleaseStringChars(JNIEnv* env, jstring string, const jchar* chars) {
1661 CHECK_JNI_ENTRY(kFlag_Default | kFlag_ExcepOkay, "Esp", env, string, chars);
1662 sc.checkNonNull(chars);
1663 if (sc.forceCopy()) {
1664 GuardedCopy::check(__FUNCTION__, chars, false);
1665 chars = (const jchar*) GuardedCopy::destroy((jchar*)chars);
1666 }
1667 baseEnv(env)->ReleaseStringChars(env, string, chars);
1668 CHECK_JNI_EXIT_VOID();
1669 }
1670
1671 static jstring NewStringUTF(JNIEnv* env, const char* bytes) {
1672 CHECK_JNI_ENTRY(kFlag_NullableUtf, "Eu", env, bytes); // TODO: show pointer and truncate string.
1673 return CHECK_JNI_EXIT("s", baseEnv(env)->NewStringUTF(env, bytes));
1674 }
1675
1676 static jsize GetStringUTFLength(JNIEnv* env, jstring string) {
1677 CHECK_JNI_ENTRY(kFlag_CritOkay, "Es", env, string);
1678 return CHECK_JNI_EXIT("I", baseEnv(env)->GetStringUTFLength(env, string));
1679 }
1680
1681 static const char* GetStringUTFChars(JNIEnv* env, jstring string, jboolean* isCopy) {
1682 CHECK_JNI_ENTRY(kFlag_CritOkay, "Esp", env, string, isCopy);
1683 const char* result = baseEnv(env)->GetStringUTFChars(env, string, isCopy);
1684 if (sc.forceCopy() && result != NULL) {
1685 result = (const char*) GuardedCopy::create(result, strlen(result) + 1, false);
1686 if (isCopy != NULL) {
1687 *isCopy = JNI_TRUE;
1688 }
1689 }
1690 return CHECK_JNI_EXIT("u", result); // TODO: show pointer and truncate string.
1691 }
1692
1693 static void ReleaseStringUTFChars(JNIEnv* env, jstring string, const char* utf) {
1694 CHECK_JNI_ENTRY(kFlag_ExcepOkay | kFlag_Release, "Esu", env, string, utf); // TODO: show pointer and truncate string.
1695 if (sc.forceCopy()) {
1696 GuardedCopy::check(__FUNCTION__, utf, false);
1697 utf = (const char*) GuardedCopy::destroy((char*)utf);
1698 }
1699 baseEnv(env)->ReleaseStringUTFChars(env, string, utf);
1700 CHECK_JNI_EXIT_VOID();
1701 }
1702
1703 static jsize GetArrayLength(JNIEnv* env, jarray array) {
1704 CHECK_JNI_ENTRY(kFlag_CritOkay, "Ea", env, array);
1705 return CHECK_JNI_EXIT("I", baseEnv(env)->GetArrayLength(env, array));
1706 }
1707
1708 static jobjectArray NewObjectArray(JNIEnv* env, jsize length, jclass elementClass, jobject initialElement) {
1709 CHECK_JNI_ENTRY(kFlag_Default, "EzcL", env, length, elementClass, initialElement);
1710 return CHECK_JNI_EXIT("a", baseEnv(env)->NewObjectArray(env, length, elementClass, initialElement));
1711 }
1712
1713 static jobject GetObjectArrayElement(JNIEnv* env, jobjectArray array, jsize index) {
1714 CHECK_JNI_ENTRY(kFlag_Default, "EaI", env, array, index);
1715 return CHECK_JNI_EXIT("L", baseEnv(env)->GetObjectArrayElement(env, array, index));
1716 }
1717
1718 static void SetObjectArrayElement(JNIEnv* env, jobjectArray array, jsize index, jobject value) {
1719 CHECK_JNI_ENTRY(kFlag_Default, "EaIL", env, array, index, value);
1720 baseEnv(env)->SetObjectArrayElement(env, array, index, value);
1721 CHECK_JNI_EXIT_VOID();
1722 }
1723
1724#define NEW_PRIMITIVE_ARRAY(_artype, _jname) \
1725 static _artype New##_jname##Array(JNIEnv* env, jsize length) { \
1726 CHECK_JNI_ENTRY(kFlag_Default, "Ez", env, length); \
1727 return CHECK_JNI_EXIT("a", baseEnv(env)->New##_jname##Array(env, length)); \
1728 }
1729NEW_PRIMITIVE_ARRAY(jbooleanArray, Boolean);
1730NEW_PRIMITIVE_ARRAY(jbyteArray, Byte);
1731NEW_PRIMITIVE_ARRAY(jcharArray, Char);
1732NEW_PRIMITIVE_ARRAY(jshortArray, Short);
1733NEW_PRIMITIVE_ARRAY(jintArray, Int);
1734NEW_PRIMITIVE_ARRAY(jlongArray, Long);
1735NEW_PRIMITIVE_ARRAY(jfloatArray, Float);
1736NEW_PRIMITIVE_ARRAY(jdoubleArray, Double);
1737
1738class ForceCopyGetChecker {
1739public:
1740 ForceCopyGetChecker(ScopedCheck& sc, jboolean* isCopy) {
1741 forceCopy = sc.forceCopy();
1742 noCopy = 0;
1743 if (forceCopy && isCopy != NULL) {
1744 /* capture this before the base call tramples on it */
1745 noCopy = *(uint32_t*) isCopy;
1746 }
1747 }
1748
1749 template<typename ResultT>
1750 ResultT check(JNIEnv* env, jarray array, jboolean* isCopy, ResultT result) {
1751 if (forceCopy && result != NULL) {
1752 if (noCopy != kNoCopyMagic) {
1753 result = reinterpret_cast<ResultT>(CreateGuardedPACopy(env, array, isCopy));
1754 }
1755 }
1756 return result;
1757 }
1758
1759 uint32_t noCopy;
1760 bool forceCopy;
1761};
1762
1763#define GET_PRIMITIVE_ARRAY_ELEMENTS(_ctype, _jname) \
1764 static _ctype* Get##_jname##ArrayElements(JNIEnv* env, _ctype##Array array, jboolean* isCopy) { \
1765 CHECK_JNI_ENTRY(kFlag_Default, "Eap", env, array, isCopy); \
1766 _ctype* result = ForceCopyGetChecker(sc, isCopy).check(env, array, isCopy, baseEnv(env)->Get##_jname##ArrayElements(env, array, isCopy)); \
1767 return CHECK_JNI_EXIT("p", result); \
1768 }
1769
1770#define RELEASE_PRIMITIVE_ARRAY_ELEMENTS(_ctype, _jname) \
1771 static void Release##_jname##ArrayElements(JNIEnv* env, _ctype##Array array, _ctype* elems, jint mode) { \
1772 CHECK_JNI_ENTRY(kFlag_Default | kFlag_ExcepOkay, "Eapr", env, array, elems, mode); \
1773 sc.checkNonNull(elems); \
1774 if (sc.forceCopy()) { \
1775 ReleaseGuardedPACopy(env, array, elems, mode); \
1776 } \
1777 baseEnv(env)->Release##_jname##ArrayElements(env, array, elems, mode); \
1778 CHECK_JNI_EXIT_VOID(); \
1779 }
1780
1781#define GET_PRIMITIVE_ARRAY_REGION(_ctype, _jname) \
1782 static void Get##_jname##ArrayRegion(JNIEnv* env, _ctype##Array array, jsize start, jsize len, _ctype* buf) { \
1783 CHECK_JNI_ENTRY(kFlag_Default, "EaIIp", env, array, start, len, buf); \
1784 baseEnv(env)->Get##_jname##ArrayRegion(env, array, start, len, buf); \
1785 CHECK_JNI_EXIT_VOID(); \
1786 }
1787
1788#define SET_PRIMITIVE_ARRAY_REGION(_ctype, _jname) \
1789 static void Set##_jname##ArrayRegion(JNIEnv* env, _ctype##Array array, jsize start, jsize len, const _ctype* buf) { \
1790 CHECK_JNI_ENTRY(kFlag_Default, "EaIIp", env, array, start, len, buf); \
1791 baseEnv(env)->Set##_jname##ArrayRegion(env, array, start, len, buf); \
1792 CHECK_JNI_EXIT_VOID(); \
1793 }
1794
1795#define PRIMITIVE_ARRAY_FUNCTIONS(_ctype, _jname, _typechar) \
1796 GET_PRIMITIVE_ARRAY_ELEMENTS(_ctype, _jname); \
1797 RELEASE_PRIMITIVE_ARRAY_ELEMENTS(_ctype, _jname); \
1798 GET_PRIMITIVE_ARRAY_REGION(_ctype, _jname); \
1799 SET_PRIMITIVE_ARRAY_REGION(_ctype, _jname);
1800
1801/* TODO: verify primitive array type matches call type */
1802PRIMITIVE_ARRAY_FUNCTIONS(jboolean, Boolean, 'Z');
1803PRIMITIVE_ARRAY_FUNCTIONS(jbyte, Byte, 'B');
1804PRIMITIVE_ARRAY_FUNCTIONS(jchar, Char, 'C');
1805PRIMITIVE_ARRAY_FUNCTIONS(jshort, Short, 'S');
1806PRIMITIVE_ARRAY_FUNCTIONS(jint, Int, 'I');
1807PRIMITIVE_ARRAY_FUNCTIONS(jlong, Long, 'J');
1808PRIMITIVE_ARRAY_FUNCTIONS(jfloat, Float, 'F');
1809PRIMITIVE_ARRAY_FUNCTIONS(jdouble, Double, 'D');
1810
1811 static jint RegisterNatives(JNIEnv* env, jclass clazz, const JNINativeMethod* methods, jint nMethods) {
1812 CHECK_JNI_ENTRY(kFlag_Default, "EcpI", env, clazz, methods, nMethods);
1813 return CHECK_JNI_EXIT("I", baseEnv(env)->RegisterNatives(env, clazz, methods, nMethods));
1814 }
1815
1816 static jint UnregisterNatives(JNIEnv* env, jclass clazz) {
1817 CHECK_JNI_ENTRY(kFlag_Default, "Ec", env, clazz);
1818 return CHECK_JNI_EXIT("I", baseEnv(env)->UnregisterNatives(env, clazz));
1819 }
1820
1821 static jint MonitorEnter(JNIEnv* env, jobject obj) {
1822 CHECK_JNI_ENTRY(kFlag_Default, "EL", env, obj);
1823 return CHECK_JNI_EXIT("I", baseEnv(env)->MonitorEnter(env, obj));
1824 }
1825
1826 static jint MonitorExit(JNIEnv* env, jobject obj) {
1827 CHECK_JNI_ENTRY(kFlag_Default | kFlag_ExcepOkay, "EL", env, obj);
1828 return CHECK_JNI_EXIT("I", baseEnv(env)->MonitorExit(env, obj));
1829 }
1830
1831 static jint GetJavaVM(JNIEnv *env, JavaVM **vm) {
1832 CHECK_JNI_ENTRY(kFlag_Default, "Ep", env, vm);
1833 return CHECK_JNI_EXIT("I", baseEnv(env)->GetJavaVM(env, vm));
1834 }
1835
1836 static void GetStringRegion(JNIEnv* env, jstring str, jsize start, jsize len, jchar* buf) {
1837 CHECK_JNI_ENTRY(kFlag_CritOkay, "EsIIp", env, str, start, len, buf);
1838 baseEnv(env)->GetStringRegion(env, str, start, len, buf);
1839 CHECK_JNI_EXIT_VOID();
1840 }
1841
1842 static void GetStringUTFRegion(JNIEnv* env, jstring str, jsize start, jsize len, char* buf) {
1843 CHECK_JNI_ENTRY(kFlag_CritOkay, "EsIIp", env, str, start, len, buf);
1844 baseEnv(env)->GetStringUTFRegion(env, str, start, len, buf);
1845 CHECK_JNI_EXIT_VOID();
1846 }
1847
1848 static void* GetPrimitiveArrayCritical(JNIEnv* env, jarray array, jboolean* isCopy) {
1849 CHECK_JNI_ENTRY(kFlag_CritGet, "Eap", env, array, isCopy);
1850 void* result = baseEnv(env)->GetPrimitiveArrayCritical(env, array, isCopy);
1851 if (sc.forceCopy() && result != NULL) {
1852 result = CreateGuardedPACopy(env, array, isCopy);
1853 }
1854 return CHECK_JNI_EXIT("p", result);
1855 }
1856
1857 static void ReleasePrimitiveArrayCritical(JNIEnv* env, jarray array, void* carray, jint mode) {
1858 CHECK_JNI_ENTRY(kFlag_CritRelease | kFlag_ExcepOkay, "Eapr", env, array, carray, mode);
1859 sc.checkNonNull(carray);
1860 if (sc.forceCopy()) {
1861 ReleaseGuardedPACopy(env, array, carray, mode);
1862 }
1863 baseEnv(env)->ReleasePrimitiveArrayCritical(env, array, carray, mode);
1864 CHECK_JNI_EXIT_VOID();
1865 }
1866
1867 static const jchar* GetStringCritical(JNIEnv* env, jstring java_string, jboolean* isCopy) {
1868 CHECK_JNI_ENTRY(kFlag_CritGet, "Esp", env, java_string, isCopy);
1869 const jchar* result = baseEnv(env)->GetStringCritical(env, java_string, isCopy);
1870 if (sc.forceCopy() && result != NULL) {
1871 ScopedJniThreadState ts(env);
1872 String* s = Decode<String*>(ts, java_string);
1873 int byteCount = s->GetLength() * 2;
1874 result = (const jchar*) GuardedCopy::create(result, byteCount, false);
1875 if (isCopy != NULL) {
1876 *isCopy = JNI_TRUE;
1877 }
1878 }
1879 return CHECK_JNI_EXIT("p", result);
1880 }
1881
1882 static void ReleaseStringCritical(JNIEnv* env, jstring string, const jchar* carray) {
1883 CHECK_JNI_ENTRY(kFlag_CritRelease | kFlag_ExcepOkay, "Esp", env, string, carray);
1884 sc.checkNonNull(carray);
1885 if (sc.forceCopy()) {
1886 GuardedCopy::check(__FUNCTION__, carray, false);
1887 carray = (const jchar*) GuardedCopy::destroy((jchar*)carray);
1888 }
1889 baseEnv(env)->ReleaseStringCritical(env, string, carray);
1890 CHECK_JNI_EXIT_VOID();
1891 }
1892
1893 static jweak NewWeakGlobalRef(JNIEnv* env, jobject obj) {
1894 CHECK_JNI_ENTRY(kFlag_Default, "EL", env, obj);
1895 return CHECK_JNI_EXIT("L", baseEnv(env)->NewWeakGlobalRef(env, obj));
1896 }
1897
1898 static jboolean ExceptionCheck(JNIEnv* env) {
1899 CHECK_JNI_ENTRY(kFlag_CritOkay | kFlag_ExcepOkay, "E", env);
1900 return CHECK_JNI_EXIT("b", baseEnv(env)->ExceptionCheck(env));
1901 }
1902
1903 static jobjectRefType GetObjectRefType(JNIEnv* env, jobject obj) {
1904 // Note: we use "Ep" rather than "EL" because this is the one JNI function
1905 // that it's okay to pass an invalid reference to.
1906 CHECK_JNI_ENTRY(kFlag_Default, "Ep", env, obj);
1907 // TODO: proper decoding of jobjectRefType!
1908 return CHECK_JNI_EXIT("I", baseEnv(env)->GetObjectRefType(env, obj));
1909 }
1910
1911 static jobject NewDirectByteBuffer(JNIEnv* env, void* address, jlong capacity) {
1912 CHECK_JNI_ENTRY(kFlag_Default, "EpJ", env, address, capacity);
1913 if (address == NULL) {
1914 LOG(ERROR) << "JNI ERROR: non-nullable address is NULL";
1915 JniAbort(__FUNCTION__);
1916 }
1917 if (capacity <= 0) {
1918 LOG(ERROR) << "JNI ERROR: capacity must be greater than 0: " << capacity;
1919 JniAbort(__FUNCTION__);
1920 }
1921 return CHECK_JNI_EXIT("L", baseEnv(env)->NewDirectByteBuffer(env, address, capacity));
1922 }
1923
1924 static void* GetDirectBufferAddress(JNIEnv* env, jobject buf) {
1925 CHECK_JNI_ENTRY(kFlag_Default, "EL", env, buf);
1926 // TODO: check that 'buf' is a java.nio.Buffer.
1927 return CHECK_JNI_EXIT("p", baseEnv(env)->GetDirectBufferAddress(env, buf));
1928 }
1929
1930 static jlong GetDirectBufferCapacity(JNIEnv* env, jobject buf) {
1931 CHECK_JNI_ENTRY(kFlag_Default, "EL", env, buf);
1932 // TODO: check that 'buf' is a java.nio.Buffer.
1933 return CHECK_JNI_EXIT("J", baseEnv(env)->GetDirectBufferCapacity(env, buf));
1934 }
1935
1936 private:
1937 static inline const JNINativeInterface* baseEnv(JNIEnv* env) {
1938 return reinterpret_cast<JNIEnvExt*>(env)->unchecked_functions;
1939 }
1940};
1941
1942const JNINativeInterface gCheckNativeInterface = {
1943 NULL, // reserved0.
1944 NULL, // reserved1.
1945 NULL, // reserved2.
1946 NULL, // reserved3.
1947 CheckJNI::GetVersion,
1948 CheckJNI::DefineClass,
1949 CheckJNI::FindClass,
1950 CheckJNI::FromReflectedMethod,
1951 CheckJNI::FromReflectedField,
1952 CheckJNI::ToReflectedMethod,
1953 CheckJNI::GetSuperclass,
1954 CheckJNI::IsAssignableFrom,
1955 CheckJNI::ToReflectedField,
1956 CheckJNI::Throw,
1957 CheckJNI::ThrowNew,
1958 CheckJNI::ExceptionOccurred,
1959 CheckJNI::ExceptionDescribe,
1960 CheckJNI::ExceptionClear,
1961 CheckJNI::FatalError,
1962 CheckJNI::PushLocalFrame,
1963 CheckJNI::PopLocalFrame,
1964 CheckJNI::NewGlobalRef,
1965 CheckJNI::DeleteGlobalRef,
1966 CheckJNI::DeleteLocalRef,
1967 CheckJNI::IsSameObject,
1968 CheckJNI::NewLocalRef,
1969 CheckJNI::EnsureLocalCapacity,
1970 CheckJNI::AllocObject,
1971 CheckJNI::NewObject,
1972 CheckJNI::NewObjectV,
1973 CheckJNI::NewObjectA,
1974 CheckJNI::GetObjectClass,
1975 CheckJNI::IsInstanceOf,
1976 CheckJNI::GetMethodID,
1977 CheckJNI::CallObjectMethod,
1978 CheckJNI::CallObjectMethodV,
1979 CheckJNI::CallObjectMethodA,
1980 CheckJNI::CallBooleanMethod,
1981 CheckJNI::CallBooleanMethodV,
1982 CheckJNI::CallBooleanMethodA,
1983 CheckJNI::CallByteMethod,
1984 CheckJNI::CallByteMethodV,
1985 CheckJNI::CallByteMethodA,
1986 CheckJNI::CallCharMethod,
1987 CheckJNI::CallCharMethodV,
1988 CheckJNI::CallCharMethodA,
1989 CheckJNI::CallShortMethod,
1990 CheckJNI::CallShortMethodV,
1991 CheckJNI::CallShortMethodA,
1992 CheckJNI::CallIntMethod,
1993 CheckJNI::CallIntMethodV,
1994 CheckJNI::CallIntMethodA,
1995 CheckJNI::CallLongMethod,
1996 CheckJNI::CallLongMethodV,
1997 CheckJNI::CallLongMethodA,
1998 CheckJNI::CallFloatMethod,
1999 CheckJNI::CallFloatMethodV,
2000 CheckJNI::CallFloatMethodA,
2001 CheckJNI::CallDoubleMethod,
2002 CheckJNI::CallDoubleMethodV,
2003 CheckJNI::CallDoubleMethodA,
2004 CheckJNI::CallVoidMethod,
2005 CheckJNI::CallVoidMethodV,
2006 CheckJNI::CallVoidMethodA,
2007 CheckJNI::CallNonvirtualObjectMethod,
2008 CheckJNI::CallNonvirtualObjectMethodV,
2009 CheckJNI::CallNonvirtualObjectMethodA,
2010 CheckJNI::CallNonvirtualBooleanMethod,
2011 CheckJNI::CallNonvirtualBooleanMethodV,
2012 CheckJNI::CallNonvirtualBooleanMethodA,
2013 CheckJNI::CallNonvirtualByteMethod,
2014 CheckJNI::CallNonvirtualByteMethodV,
2015 CheckJNI::CallNonvirtualByteMethodA,
2016 CheckJNI::CallNonvirtualCharMethod,
2017 CheckJNI::CallNonvirtualCharMethodV,
2018 CheckJNI::CallNonvirtualCharMethodA,
2019 CheckJNI::CallNonvirtualShortMethod,
2020 CheckJNI::CallNonvirtualShortMethodV,
2021 CheckJNI::CallNonvirtualShortMethodA,
2022 CheckJNI::CallNonvirtualIntMethod,
2023 CheckJNI::CallNonvirtualIntMethodV,
2024 CheckJNI::CallNonvirtualIntMethodA,
2025 CheckJNI::CallNonvirtualLongMethod,
2026 CheckJNI::CallNonvirtualLongMethodV,
2027 CheckJNI::CallNonvirtualLongMethodA,
2028 CheckJNI::CallNonvirtualFloatMethod,
2029 CheckJNI::CallNonvirtualFloatMethodV,
2030 CheckJNI::CallNonvirtualFloatMethodA,
2031 CheckJNI::CallNonvirtualDoubleMethod,
2032 CheckJNI::CallNonvirtualDoubleMethodV,
2033 CheckJNI::CallNonvirtualDoubleMethodA,
2034 CheckJNI::CallNonvirtualVoidMethod,
2035 CheckJNI::CallNonvirtualVoidMethodV,
2036 CheckJNI::CallNonvirtualVoidMethodA,
2037 CheckJNI::GetFieldID,
2038 CheckJNI::GetObjectField,
2039 CheckJNI::GetBooleanField,
2040 CheckJNI::GetByteField,
2041 CheckJNI::GetCharField,
2042 CheckJNI::GetShortField,
2043 CheckJNI::GetIntField,
2044 CheckJNI::GetLongField,
2045 CheckJNI::GetFloatField,
2046 CheckJNI::GetDoubleField,
2047 CheckJNI::SetObjectField,
2048 CheckJNI::SetBooleanField,
2049 CheckJNI::SetByteField,
2050 CheckJNI::SetCharField,
2051 CheckJNI::SetShortField,
2052 CheckJNI::SetIntField,
2053 CheckJNI::SetLongField,
2054 CheckJNI::SetFloatField,
2055 CheckJNI::SetDoubleField,
2056 CheckJNI::GetStaticMethodID,
2057 CheckJNI::CallStaticObjectMethod,
2058 CheckJNI::CallStaticObjectMethodV,
2059 CheckJNI::CallStaticObjectMethodA,
2060 CheckJNI::CallStaticBooleanMethod,
2061 CheckJNI::CallStaticBooleanMethodV,
2062 CheckJNI::CallStaticBooleanMethodA,
2063 CheckJNI::CallStaticByteMethod,
2064 CheckJNI::CallStaticByteMethodV,
2065 CheckJNI::CallStaticByteMethodA,
2066 CheckJNI::CallStaticCharMethod,
2067 CheckJNI::CallStaticCharMethodV,
2068 CheckJNI::CallStaticCharMethodA,
2069 CheckJNI::CallStaticShortMethod,
2070 CheckJNI::CallStaticShortMethodV,
2071 CheckJNI::CallStaticShortMethodA,
2072 CheckJNI::CallStaticIntMethod,
2073 CheckJNI::CallStaticIntMethodV,
2074 CheckJNI::CallStaticIntMethodA,
2075 CheckJNI::CallStaticLongMethod,
2076 CheckJNI::CallStaticLongMethodV,
2077 CheckJNI::CallStaticLongMethodA,
2078 CheckJNI::CallStaticFloatMethod,
2079 CheckJNI::CallStaticFloatMethodV,
2080 CheckJNI::CallStaticFloatMethodA,
2081 CheckJNI::CallStaticDoubleMethod,
2082 CheckJNI::CallStaticDoubleMethodV,
2083 CheckJNI::CallStaticDoubleMethodA,
2084 CheckJNI::CallStaticVoidMethod,
2085 CheckJNI::CallStaticVoidMethodV,
2086 CheckJNI::CallStaticVoidMethodA,
2087 CheckJNI::GetStaticFieldID,
2088 CheckJNI::GetStaticObjectField,
2089 CheckJNI::GetStaticBooleanField,
2090 CheckJNI::GetStaticByteField,
2091 CheckJNI::GetStaticCharField,
2092 CheckJNI::GetStaticShortField,
2093 CheckJNI::GetStaticIntField,
2094 CheckJNI::GetStaticLongField,
2095 CheckJNI::GetStaticFloatField,
2096 CheckJNI::GetStaticDoubleField,
2097 CheckJNI::SetStaticObjectField,
2098 CheckJNI::SetStaticBooleanField,
2099 CheckJNI::SetStaticByteField,
2100 CheckJNI::SetStaticCharField,
2101 CheckJNI::SetStaticShortField,
2102 CheckJNI::SetStaticIntField,
2103 CheckJNI::SetStaticLongField,
2104 CheckJNI::SetStaticFloatField,
2105 CheckJNI::SetStaticDoubleField,
2106 CheckJNI::NewString,
2107 CheckJNI::GetStringLength,
2108 CheckJNI::GetStringChars,
2109 CheckJNI::ReleaseStringChars,
2110 CheckJNI::NewStringUTF,
2111 CheckJNI::GetStringUTFLength,
2112 CheckJNI::GetStringUTFChars,
2113 CheckJNI::ReleaseStringUTFChars,
2114 CheckJNI::GetArrayLength,
2115 CheckJNI::NewObjectArray,
2116 CheckJNI::GetObjectArrayElement,
2117 CheckJNI::SetObjectArrayElement,
2118 CheckJNI::NewBooleanArray,
2119 CheckJNI::NewByteArray,
2120 CheckJNI::NewCharArray,
2121 CheckJNI::NewShortArray,
2122 CheckJNI::NewIntArray,
2123 CheckJNI::NewLongArray,
2124 CheckJNI::NewFloatArray,
2125 CheckJNI::NewDoubleArray,
2126 CheckJNI::GetBooleanArrayElements,
2127 CheckJNI::GetByteArrayElements,
2128 CheckJNI::GetCharArrayElements,
2129 CheckJNI::GetShortArrayElements,
2130 CheckJNI::GetIntArrayElements,
2131 CheckJNI::GetLongArrayElements,
2132 CheckJNI::GetFloatArrayElements,
2133 CheckJNI::GetDoubleArrayElements,
2134 CheckJNI::ReleaseBooleanArrayElements,
2135 CheckJNI::ReleaseByteArrayElements,
2136 CheckJNI::ReleaseCharArrayElements,
2137 CheckJNI::ReleaseShortArrayElements,
2138 CheckJNI::ReleaseIntArrayElements,
2139 CheckJNI::ReleaseLongArrayElements,
2140 CheckJNI::ReleaseFloatArrayElements,
2141 CheckJNI::ReleaseDoubleArrayElements,
2142 CheckJNI::GetBooleanArrayRegion,
2143 CheckJNI::GetByteArrayRegion,
2144 CheckJNI::GetCharArrayRegion,
2145 CheckJNI::GetShortArrayRegion,
2146 CheckJNI::GetIntArrayRegion,
2147 CheckJNI::GetLongArrayRegion,
2148 CheckJNI::GetFloatArrayRegion,
2149 CheckJNI::GetDoubleArrayRegion,
2150 CheckJNI::SetBooleanArrayRegion,
2151 CheckJNI::SetByteArrayRegion,
2152 CheckJNI::SetCharArrayRegion,
2153 CheckJNI::SetShortArrayRegion,
2154 CheckJNI::SetIntArrayRegion,
2155 CheckJNI::SetLongArrayRegion,
2156 CheckJNI::SetFloatArrayRegion,
2157 CheckJNI::SetDoubleArrayRegion,
2158 CheckJNI::RegisterNatives,
2159 CheckJNI::UnregisterNatives,
2160 CheckJNI::MonitorEnter,
2161 CheckJNI::MonitorExit,
2162 CheckJNI::GetJavaVM,
2163 CheckJNI::GetStringRegion,
2164 CheckJNI::GetStringUTFRegion,
2165 CheckJNI::GetPrimitiveArrayCritical,
2166 CheckJNI::ReleasePrimitiveArrayCritical,
2167 CheckJNI::GetStringCritical,
2168 CheckJNI::ReleaseStringCritical,
2169 CheckJNI::NewWeakGlobalRef,
2170 CheckJNI::DeleteWeakGlobalRef,
2171 CheckJNI::ExceptionCheck,
2172 CheckJNI::NewDirectByteBuffer,
2173 CheckJNI::GetDirectBufferAddress,
2174 CheckJNI::GetDirectBufferCapacity,
2175 CheckJNI::GetObjectRefType,
2176};
2177
2178const JNINativeInterface* GetCheckJniNativeInterface() {
2179 return &gCheckNativeInterface;
2180}
2181
2182class CheckJII {
2183public:
2184 static jint DestroyJavaVM(JavaVM* vm) {
2185 ScopedCheck sc(false, __FUNCTION__);
2186 sc.check(true, "v", vm);
2187 return CHECK_JNI_EXIT("I", baseVm(vm)->DestroyJavaVM(vm));
2188 }
2189
2190 static jint AttachCurrentThread(JavaVM* vm, JNIEnv** p_env, void* thr_args) {
2191 ScopedCheck sc(false, __FUNCTION__);
2192 sc.check(true, "vpp", vm, p_env, thr_args);
2193 return CHECK_JNI_EXIT("I", baseVm(vm)->AttachCurrentThread(vm, p_env, thr_args));
2194 }
2195
2196 static jint AttachCurrentThreadAsDaemon(JavaVM* vm, JNIEnv** p_env, void* thr_args) {
2197 ScopedCheck sc(false, __FUNCTION__);
2198 sc.check(true, "vpp", vm, p_env, thr_args);
2199 return CHECK_JNI_EXIT("I", baseVm(vm)->AttachCurrentThreadAsDaemon(vm, p_env, thr_args));
2200 }
2201
2202 static jint DetachCurrentThread(JavaVM* vm) {
2203 ScopedCheck sc(true, __FUNCTION__);
2204 sc.check(true, "v", vm);
2205 return CHECK_JNI_EXIT("I", baseVm(vm)->DetachCurrentThread(vm));
2206 }
2207
2208 static jint GetEnv(JavaVM* vm, void** env, jint version) {
2209 ScopedCheck sc(true, __FUNCTION__);
2210 sc.check(true, "v", vm);
2211 return CHECK_JNI_EXIT("I", baseVm(vm)->GetEnv(vm, env, version));
2212 }
2213
2214 private:
2215 static inline const JNIInvokeInterface* baseVm(JavaVM* vm) {
2216 return reinterpret_cast<JavaVMExt*>(vm)->unchecked_functions;
2217 }
2218};
2219
2220const JNIInvokeInterface gCheckInvokeInterface = {
2221 NULL, // reserved0
2222 NULL, // reserved1
2223 NULL, // reserved2
2224 CheckJII::DestroyJavaVM,
2225 CheckJII::AttachCurrentThread,
2226 CheckJII::DetachCurrentThread,
2227 CheckJII::GetEnv,
2228 CheckJII::AttachCurrentThreadAsDaemon
2229};
2230
2231const JNIInvokeInterface* GetCheckJniInvokeInterface() {
2232 return &gCheckInvokeInterface;
2233}
2234
2235} // namespace art