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