blob: 38bc8186d58579ffb6516fc4816680aee2954c06 [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
Andreas Gampe277ccbd2014-11-03 21:36:10 -080017#include "check_jni.h"
Elliott Hughesa2501992011-08-26 19:39:54 -070018
Andreas Gampeef4afe92015-07-27 21:03:25 -070019#include <iomanip>
Elliott Hughesa2501992011-08-26 19:39:54 -070020#include <sys/mman.h>
21#include <zlib.h>
22
Mathieu Chartierc7853442015-03-27 14:35:38 -070023#include "art_field-inl.h"
Mathieu Chartiere401d142015-04-22 13:56:20 -070024#include "art_method-inl.h"
Elliott Hughes07ed66b2012-12-12 18:34:25 -080025#include "base/logging.h"
Ian Rogersc7dd2952014-10-21 23:31:19 -070026#include "base/to_str.h"
Elliott Hughesa2501992011-08-26 19:39:54 -070027#include "class_linker.h"
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080028#include "class_linker-inl.h"
Ian Rogers4f6ad8a2013-03-18 15:27:28 -070029#include "dex_file-inl.h"
Ian Rogers1d54e732013-05-02 21:10:01 -070030#include "gc/space/space.h"
Ian Rogers68d8b422014-07-17 11:09:10 -070031#include "java_vm_ext.h"
Andreas Gampe277ccbd2014-11-03 21:36:10 -080032#include "jni_internal.h"
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080033#include "mirror/class-inl.h"
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080034#include "mirror/object-inl.h"
35#include "mirror/object_array-inl.h"
Ian Rogersb0fa5dc2014-04-28 16:47:08 -070036#include "mirror/string-inl.h"
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080037#include "mirror/throwable.h"
Jeff Hao58df3272013-04-22 15:28:53 -070038#include "runtime.h"
Ian Rogers00f7d0e2012-07-19 15:28:27 -070039#include "scoped_thread_state_change.h"
Elliott Hughesa2501992011-08-26 19:39:54 -070040#include "thread.h"
Ian Rogers68d8b422014-07-17 11:09:10 -070041#include "well_known_classes.h"
Elliott Hughesa2501992011-08-26 19:39:54 -070042
43namespace art {
44
Elliott Hughesa2501992011-08-26 19:39:54 -070045/*
46 * ===========================================================================
47 * JNI function helpers
48 * ===========================================================================
49 */
50
Elliott Hughes3f6635a2012-06-19 13:37:49 -070051// Flags passed into ScopedCheck.
Elliott Hughesa2501992011-08-26 19:39:54 -070052#define kFlag_Default 0x0000
53
Elliott Hughes3f6635a2012-06-19 13:37:49 -070054#define kFlag_CritBad 0x0000 // Calling while in critical is not allowed.
55#define kFlag_CritOkay 0x0001 // Calling while in critical is allowed.
56#define kFlag_CritGet 0x0002 // This is a critical "get".
57#define kFlag_CritRelease 0x0003 // This is a critical "release".
58#define kFlag_CritMask 0x0003 // Bit mask to get "crit" value.
Elliott Hughesa2501992011-08-26 19:39:54 -070059
Elliott Hughes3f6635a2012-06-19 13:37:49 -070060#define kFlag_ExcepBad 0x0000 // Raised exceptions are not allowed.
61#define kFlag_ExcepOkay 0x0004 // Raised exceptions are allowed.
Elliott Hughesa2501992011-08-26 19:39:54 -070062
Elliott Hughes3f6635a2012-06-19 13:37:49 -070063#define kFlag_Release 0x0010 // Are we in a non-critical release function?
64#define kFlag_NullableUtf 0x0020 // Are our UTF parameters nullable?
Elliott Hughesa2501992011-08-26 19:39:54 -070065
Elliott Hughes3f6635a2012-06-19 13:37:49 -070066#define kFlag_Invocation 0x8000 // Part of the invocation interface (JavaVM*).
Elliott Hughesa2501992011-08-26 19:39:54 -070067
Elliott Hughes485cac42011-12-09 17:49:35 -080068#define kFlag_ForceTrace 0x80000000 // Add this to a JNI function's flags if you want to trace every call.
Ian Rogers68d8b422014-07-17 11:09:10 -070069/*
70 * Java primitive types:
71 * B - jbyte
72 * C - jchar
73 * D - jdouble
74 * F - jfloat
75 * I - jint
76 * J - jlong
77 * S - jshort
78 * Z - jboolean (shown as true and false)
79 * V - void
80 *
81 * Java reference types:
82 * L - jobject
83 * a - jarray
84 * c - jclass
85 * s - jstring
86 * t - jthrowable
87 *
88 * JNI types:
89 * b - jboolean (shown as JNI_TRUE and JNI_FALSE)
90 * f - jfieldID
91 * i - JNI error value (JNI_OK, JNI_ERR, JNI_EDETACHED, JNI_EVERSION)
92 * m - jmethodID
93 * p - void*
94 * r - jint (for release mode arguments)
95 * u - const char* (Modified UTF-8)
96 * z - jsize (for lengths; use i if negative values are okay)
97 * v - JavaVM*
98 * w - jobjectRefType
99 * E - JNIEnv*
100 * . - no argument; just print "..." (used for varargs JNI calls)
101 *
102 */
103union JniValueType {
104 jarray a;
105 jboolean b;
106 jclass c;
107 jfieldID f;
108 jint i;
109 jmethodID m;
110 const void* p; // Pointer.
111 jint r; // Release mode.
112 jstring s;
113 jthrowable t;
114 const char* u; // Modified UTF-8.
115 JavaVM* v;
116 jobjectRefType w;
117 jsize z;
118 jbyte B;
119 jchar C;
120 jdouble D;
121 JNIEnv* E;
122 jfloat F;
123 jint I;
124 jlong J;
125 jobject L;
126 jshort S;
127 const void* V; // void
128 jboolean Z;
Elliott Hughesa0957642011-09-02 14:27:33 -0700129};
130
Elliott Hughesa2501992011-08-26 19:39:54 -0700131class ScopedCheck {
Elliott Hughesba8eee12012-01-24 20:25:24 -0800132 public:
Ian Rogers68d8b422014-07-17 11:09:10 -0700133 explicit ScopedCheck(int flags, const char* functionName, bool has_method = true)
134 : function_name_(functionName), flags_(flags), indent_(0), has_method_(has_method) {
Elliott Hughesa2501992011-08-26 19:39:54 -0700135 }
136
Ian Rogers68d8b422014-07-17 11:09:10 -0700137 ~ScopedCheck() {}
Elliott Hughesa2501992011-08-26 19:39:54 -0700138
Elliott Hughes81ff3182012-03-23 20:35:56 -0700139 // Checks that 'class_name' is a valid "fully-qualified" JNI class name, like "java/lang/Thread"
140 // or "[Ljava/lang/Object;". A ClassLoader can actually normalize class names a couple of
141 // times, so using "java.lang.Thread" instead of "java/lang/Thread" might work in some
142 // circumstances, but this is incorrect.
Ian Rogers68d8b422014-07-17 11:09:10 -0700143 bool CheckClassName(const char* class_name) {
Ian Rogers2d10b202014-05-12 19:15:18 -0700144 if ((class_name == nullptr) || !IsValidJniClassName(class_name)) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700145 AbortF("illegal class name '%s'\n"
146 " (should be of the form 'package/Class', [Lpackage/Class;' or '[[B')",
147 class_name);
148 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -0700149 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700150 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -0700151 }
152
153 /*
154 * Verify that this instance field ID is valid for this object.
155 *
156 * Assumes "jobj" has already been validated.
157 */
Ian Rogers68d8b422014-07-17 11:09:10 -0700158 bool CheckInstanceFieldID(ScopedObjectAccess& soa, jobject java_object, jfieldID fid)
Mathieu Chartier90443472015-07-16 20:32:27 -0700159 SHARED_REQUIRES(Locks::mutator_lock_) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700160 mirror::Object* o = soa.Decode<mirror::Object*>(java_object);
161 if (o == nullptr) {
162 AbortF("field operation on NULL object: %p", java_object);
163 return false;
164 }
165 if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(o)) {
Mathieu Chartier4c13a3f2014-07-14 14:57:16 -0700166 Runtime::Current()->GetHeap()->DumpSpaces(LOG(ERROR));
Ian Rogers68d8b422014-07-17 11:09:10 -0700167 AbortF("field operation on invalid %s: %p",
168 ToStr<IndirectRefKind>(GetIndirectRefKind(java_object)).c_str(),
169 java_object);
170 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -0700171 }
172
Mathieu Chartierc7853442015-03-27 14:35:38 -0700173 ArtField* f = CheckFieldID(soa, fid);
Ian Rogersef7d42f2014-01-06 12:55:46 -0800174 if (f == nullptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700175 return false;
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700176 }
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800177 mirror::Class* c = o->GetClass();
Mathieu Chartier61c5ebc2014-06-05 17:42:53 -0700178 if (c->FindInstanceField(f->GetName(), f->GetTypeDescriptor()) == nullptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700179 AbortF("jfieldID %s not valid for an object of class %s",
180 PrettyField(f).c_str(), PrettyTypeOf(o).c_str());
181 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -0700182 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700183 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -0700184 }
185
186 /*
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700187 * Verify that the pointer value is non-null.
Elliott Hughesa2501992011-08-26 19:39:54 -0700188 */
Ian Rogers68d8b422014-07-17 11:09:10 -0700189 bool CheckNonNull(const void* ptr) {
190 if (UNLIKELY(ptr == nullptr)) {
191 AbortF("non-nullable argument was NULL");
192 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -0700193 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700194 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -0700195 }
196
197 /*
198 * Verify that the method's return type matches the type of call.
199 * 'expectedType' will be "L" for all objects, including arrays.
200 */
Ian Rogers68d8b422014-07-17 11:09:10 -0700201 bool CheckMethodAndSig(ScopedObjectAccess& soa, jobject jobj, jclass jc,
202 jmethodID mid, Primitive::Type type, InvokeType invoke)
Mathieu Chartier90443472015-07-16 20:32:27 -0700203 SHARED_REQUIRES(Locks::mutator_lock_) {
Mathieu Chartiere401d142015-04-22 13:56:20 -0700204 ArtMethod* m = CheckMethodID(soa, mid);
Ian Rogersef7d42f2014-01-06 12:55:46 -0800205 if (m == nullptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700206 return false;
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700207 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700208 if (type != Primitive::GetType(m->GetShorty()[0])) {
209 AbortF("the return type of %s does not match %s", function_name_, PrettyMethod(m).c_str());
210 return false;
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700211 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700212 bool is_static = (invoke == kStatic);
213 if (is_static != m->IsStatic()) {
214 if (is_static) {
215 AbortF("calling non-static method %s with %s",
216 PrettyMethod(m).c_str(), function_name_);
Elliott Hughesa2501992011-08-26 19:39:54 -0700217 } else {
Ian Rogers68d8b422014-07-17 11:09:10 -0700218 AbortF("calling static method %s with %s",
219 PrettyMethod(m).c_str(), function_name_);
220 }
221 return false;
222 }
223 if (invoke != kVirtual) {
224 mirror::Class* c = soa.Decode<mirror::Class*>(jc);
225 if (!m->GetDeclaringClass()->IsAssignableFrom(c)) {
226 AbortF("can't call %s %s with class %s", invoke == kStatic ? "static" : "nonvirtual",
227 PrettyMethod(m).c_str(), PrettyClass(c).c_str());
228 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -0700229 }
Elliott Hughesa2501992011-08-26 19:39:54 -0700230 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700231 if (invoke != kStatic) {
232 mirror::Object* o = soa.Decode<mirror::Object*>(jobj);
Mathieu Chartiera1e78fa2014-08-20 12:09:38 -0700233 if (o == nullptr) {
234 AbortF("can't call %s on null object", PrettyMethod(m).c_str());
235 return false;
236 } else if (!o->InstanceOf(m->GetDeclaringClass())) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700237 AbortF("can't call %s on instance of %s", PrettyMethod(m).c_str(), PrettyTypeOf(o).c_str());
238 return false;
239 }
240 }
241 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -0700242 }
243
244 /*
245 * Verify that this static field ID is valid for this class.
246 *
247 * Assumes "java_class" has already been validated.
248 */
Ian Rogers68d8b422014-07-17 11:09:10 -0700249 bool CheckStaticFieldID(ScopedObjectAccess& soa, jclass java_class, jfieldID fid)
Mathieu Chartier90443472015-07-16 20:32:27 -0700250 SHARED_REQUIRES(Locks::mutator_lock_) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700251 mirror::Class* c = soa.Decode<mirror::Class*>(java_class);
Mathieu Chartierc7853442015-03-27 14:35:38 -0700252 ArtField* f = CheckFieldID(soa, fid);
Ian Rogersef7d42f2014-01-06 12:55:46 -0800253 if (f == nullptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700254 return false;
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700255 }
Elliott Hughesa2501992011-08-26 19:39:54 -0700256 if (f->GetDeclaringClass() != c) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700257 AbortF("static jfieldID %p not valid for class %s", fid, PrettyClass(c).c_str());
258 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -0700259 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700260 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -0700261 }
262
263 /*
Elliott Hughese84278b2012-03-22 10:06:53 -0700264 * Verify that "mid" is appropriate for "java_class".
Elliott Hughesa2501992011-08-26 19:39:54 -0700265 *
266 * A mismatch isn't dangerous, because the jmethodID defines the class. In
Elliott Hughese84278b2012-03-22 10:06:53 -0700267 * fact, java_class is unused in the implementation. It's best if we don't
Elliott Hughesa2501992011-08-26 19:39:54 -0700268 * allow bad code in the system though.
269 *
Elliott Hughese84278b2012-03-22 10:06:53 -0700270 * Instances of "java_class" must be instances of the method's declaring class.
Elliott Hughesa2501992011-08-26 19:39:54 -0700271 */
Ian Rogers68d8b422014-07-17 11:09:10 -0700272 bool CheckStaticMethod(ScopedObjectAccess& soa, jclass java_class, jmethodID mid)
Mathieu Chartier90443472015-07-16 20:32:27 -0700273 SHARED_REQUIRES(Locks::mutator_lock_) {
Mathieu Chartiere401d142015-04-22 13:56:20 -0700274 ArtMethod* m = CheckMethodID(soa, mid);
Ian Rogersef7d42f2014-01-06 12:55:46 -0800275 if (m == nullptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700276 return false;
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700277 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700278 mirror::Class* c = soa.Decode<mirror::Class*>(java_class);
Brian Carlstrom67fe2b42013-10-15 18:51:42 -0700279 if (!m->GetDeclaringClass()->IsAssignableFrom(c)) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700280 AbortF("can't call static %s on class %s", PrettyMethod(m).c_str(), PrettyClass(c).c_str());
281 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -0700282 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700283 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -0700284 }
285
286 /*
287 * Verify that "mid" is appropriate for "jobj".
288 *
289 * Make sure the object is an instance of the method's declaring class.
290 * (Note the mid might point to a declaration in an interface; this
291 * will be handled automatically by the instanceof check.)
292 */
Ian Rogers68d8b422014-07-17 11:09:10 -0700293 bool CheckVirtualMethod(ScopedObjectAccess& soa, jobject java_object, jmethodID mid)
Mathieu Chartier90443472015-07-16 20:32:27 -0700294 SHARED_REQUIRES(Locks::mutator_lock_) {
Mathieu Chartiere401d142015-04-22 13:56:20 -0700295 ArtMethod* m = CheckMethodID(soa, mid);
Ian Rogersef7d42f2014-01-06 12:55:46 -0800296 if (m == nullptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700297 return false;
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700298 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700299 mirror::Object* o = soa.Decode<mirror::Object*>(java_object);
Mathieu Chartiera1e78fa2014-08-20 12:09:38 -0700300 if (o == nullptr) {
301 AbortF("can't call %s on null object", PrettyMethod(m).c_str());
302 return false;
303 } else if (!o->InstanceOf(m->GetDeclaringClass())) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700304 AbortF("can't call %s on instance of %s", PrettyMethod(m).c_str(), PrettyTypeOf(o).c_str());
305 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -0700306 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700307 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -0700308 }
309
310 /**
311 * The format string is a sequence of the following characters,
312 * and must be followed by arguments of the corresponding types
313 * in the same order.
314 *
315 * Java primitive types:
316 * B - jbyte
317 * C - jchar
318 * D - jdouble
319 * F - jfloat
320 * I - jint
321 * J - jlong
322 * S - jshort
323 * Z - jboolean (shown as true and false)
324 * V - void
325 *
326 * Java reference types:
327 * L - jobject
328 * a - jarray
329 * c - jclass
330 * s - jstring
331 *
332 * JNI types:
333 * b - jboolean (shown as JNI_TRUE and JNI_FALSE)
334 * f - jfieldID
335 * m - jmethodID
336 * p - void*
337 * r - jint (for release mode arguments)
Elliott Hughes78090d12011-10-07 14:31:47 -0700338 * u - const char* (Modified UTF-8)
Elliott Hughesa2501992011-08-26 19:39:54 -0700339 * z - jsize (for lengths; use i if negative values are okay)
340 * v - JavaVM*
341 * E - JNIEnv*
342 * . - no argument; just print "..." (used for varargs JNI calls)
343 *
344 * Use the kFlag_NullableUtf flag where 'u' field(s) are nullable.
345 */
Ian Rogers68d8b422014-07-17 11:09:10 -0700346 bool Check(ScopedObjectAccess& soa, bool entry, const char* fmt, JniValueType* args)
Mathieu Chartier90443472015-07-16 20:32:27 -0700347 SHARED_REQUIRES(Locks::mutator_lock_) {
Mathieu Chartiere401d142015-04-22 13:56:20 -0700348 ArtMethod* traceMethod = nullptr;
Ian Rogers68d8b422014-07-17 11:09:10 -0700349 if (has_method_ && soa.Vm()->IsTracingEnabled()) {
Elliott Hughesa2501992011-08-26 19:39:54 -0700350 // We need to guard some of the invocation interface's calls: a bad caller might
351 // use DetachCurrentThread or GetEnv on a thread that's not yet attached.
Elliott Hughesa0957642011-09-02 14:27:33 -0700352 Thread* self = Thread::Current();
Ian Rogersef7d42f2014-01-06 12:55:46 -0800353 if ((flags_ & kFlag_Invocation) == 0 || self != nullptr) {
354 traceMethod = self->GetCurrentMethod(nullptr);
Elliott Hughesa2501992011-08-26 19:39:54 -0700355 }
356 }
Elliott Hughesa0957642011-09-02 14:27:33 -0700357
Ian Rogersef7d42f2014-01-06 12:55:46 -0800358 if (((flags_ & kFlag_ForceTrace) != 0) ||
Ian Rogers68d8b422014-07-17 11:09:10 -0700359 (traceMethod != nullptr && soa.Vm()->ShouldTrace(traceMethod))) {
Elliott Hughesa2501992011-08-26 19:39:54 -0700360 std::string msg;
Ian Rogers68d8b422014-07-17 11:09:10 -0700361 for (size_t i = 0; fmt[i] != '\0'; ++i) {
362 TracePossibleHeapValue(soa, entry, fmt[i], args[i], &msg);
363 if (fmt[i + 1] != '\0') {
Elliott Hughesa2501992011-08-26 19:39:54 -0700364 StringAppendF(&msg, ", ");
365 }
366 }
Elliott Hughesa2501992011-08-26 19:39:54 -0700367
Elliott Hughes485cac42011-12-09 17:49:35 -0800368 if ((flags_ & kFlag_ForceTrace) != 0) {
369 LOG(INFO) << "JNI: call to " << function_name_ << "(" << msg << ")";
370 } else if (entry) {
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700371 if (has_method_) {
Elliott Hughesa0957642011-09-02 14:27:33 -0700372 std::string methodName(PrettyMethod(traceMethod, false));
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700373 LOG(INFO) << "JNI: " << methodName << " -> " << function_name_ << "(" << msg << ")";
374 indent_ = methodName.size() + 1;
Elliott Hughesa2501992011-08-26 19:39:54 -0700375 } else {
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700376 LOG(INFO) << "JNI: -> " << function_name_ << "(" << msg << ")";
377 indent_ = 0;
Elliott Hughesa2501992011-08-26 19:39:54 -0700378 }
379 } else {
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700380 LOG(INFO) << StringPrintf("JNI: %*s<- %s returned %s", indent_, "", function_name_, msg.c_str());
Elliott Hughesa2501992011-08-26 19:39:54 -0700381 }
382 }
383
384 // We always do the thorough checks on entry, and never on exit...
385 if (entry) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700386 for (size_t i = 0; fmt[i] != '\0'; ++i) {
387 if (!CheckPossibleHeapValue(soa, fmt[i], args[i])) {
388 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -0700389 }
390 }
Elliott Hughesa2501992011-08-26 19:39:54 -0700391 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700392 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -0700393 }
394
Ian Rogers68d8b422014-07-17 11:09:10 -0700395 bool CheckNonHeap(JavaVMExt* vm, bool entry, const char* fmt, JniValueType* args) {
396 bool should_trace = (flags_ & kFlag_ForceTrace) != 0;
Andreas Gampedef194e2015-02-19 15:19:50 -0800397 if (!should_trace && vm != nullptr && vm->IsTracingEnabled()) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700398 // We need to guard some of the invocation interface's calls: a bad caller might
399 // use DetachCurrentThread or GetEnv on a thread that's not yet attached.
400 Thread* self = Thread::Current();
401 if ((flags_ & kFlag_Invocation) == 0 || self != nullptr) {
402 ScopedObjectAccess soa(self);
Mathieu Chartiere401d142015-04-22 13:56:20 -0700403 ArtMethod* traceMethod = self->GetCurrentMethod(nullptr);
Ian Rogers68d8b422014-07-17 11:09:10 -0700404 should_trace = (traceMethod != nullptr && vm->ShouldTrace(traceMethod));
405 }
406 }
407 if (should_trace) {
408 std::string msg;
409 for (size_t i = 0; fmt[i] != '\0'; ++i) {
410 TraceNonHeapValue(fmt[i], args[i], &msg);
411 if (fmt[i + 1] != '\0') {
412 StringAppendF(&msg, ", ");
413 }
414 }
415
416 if ((flags_ & kFlag_ForceTrace) != 0) {
417 LOG(INFO) << "JNI: call to " << function_name_ << "(" << msg << ")";
418 } else if (entry) {
419 if (has_method_) {
420 Thread* self = Thread::Current();
421 ScopedObjectAccess soa(self);
Mathieu Chartiere401d142015-04-22 13:56:20 -0700422 ArtMethod* traceMethod = self->GetCurrentMethod(nullptr);
Ian Rogers68d8b422014-07-17 11:09:10 -0700423 std::string methodName(PrettyMethod(traceMethod, false));
424 LOG(INFO) << "JNI: " << methodName << " -> " << function_name_ << "(" << msg << ")";
425 indent_ = methodName.size() + 1;
426 } else {
427 LOG(INFO) << "JNI: -> " << function_name_ << "(" << msg << ")";
428 indent_ = 0;
429 }
430 } else {
431 LOG(INFO) << StringPrintf("JNI: %*s<- %s returned %s", indent_, "", function_name_, msg.c_str());
432 }
433 }
434
435 // We always do the thorough checks on entry, and never on exit...
436 if (entry) {
437 for (size_t i = 0; fmt[i] != '\0'; ++i) {
438 if (!CheckNonHeapValue(fmt[i], args[i])) {
439 return false;
440 }
441 }
442 }
443 return true;
444 }
445
446 bool CheckReflectedMethod(ScopedObjectAccess& soa, jobject jmethod)
Mathieu Chartier90443472015-07-16 20:32:27 -0700447 SHARED_REQUIRES(Locks::mutator_lock_) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700448 mirror::Object* method = soa.Decode<mirror::Object*>(jmethod);
449 if (method == nullptr) {
450 AbortF("expected non-null method");
451 return false;
452 }
453 mirror::Class* c = method->GetClass();
454 if (soa.Decode<mirror::Class*>(WellKnownClasses::java_lang_reflect_Method) != c &&
455 soa.Decode<mirror::Class*>(WellKnownClasses::java_lang_reflect_Constructor) != c) {
456 AbortF("expected java.lang.reflect.Method or "
457 "java.lang.reflect.Constructor but got object of type %s: %p",
458 PrettyTypeOf(method).c_str(), jmethod);
459 return false;
460 }
461 return true;
462 }
463
464 bool CheckConstructor(ScopedObjectAccess& soa, jmethodID mid)
Mathieu Chartier90443472015-07-16 20:32:27 -0700465 SHARED_REQUIRES(Locks::mutator_lock_) {
Mathieu Chartiere401d142015-04-22 13:56:20 -0700466 ArtMethod* method = soa.DecodeMethod(mid);
Ian Rogers68d8b422014-07-17 11:09:10 -0700467 if (method == nullptr) {
468 AbortF("expected non-null constructor");
469 return false;
470 }
471 if (!method->IsConstructor() || method->IsStatic()) {
Mathieu Chartiere401d142015-04-22 13:56:20 -0700472 AbortF("expected a constructor but %s: %p", PrettyMethod(method).c_str(), mid);
Ian Rogers68d8b422014-07-17 11:09:10 -0700473 return false;
474 }
475 return true;
476 }
477
478 bool CheckReflectedField(ScopedObjectAccess& soa, jobject jfield)
Mathieu Chartier90443472015-07-16 20:32:27 -0700479 SHARED_REQUIRES(Locks::mutator_lock_) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700480 mirror::Object* field = soa.Decode<mirror::Object*>(jfield);
481 if (field == nullptr) {
482 AbortF("expected non-null java.lang.reflect.Field");
483 return false;
484 }
485 mirror::Class* c = field->GetClass();
486 if (soa.Decode<mirror::Class*>(WellKnownClasses::java_lang_reflect_Field) != c) {
487 AbortF("expected java.lang.reflect.Field but got object of type %s: %p",
488 PrettyTypeOf(field).c_str(), jfield);
489 return false;
490 }
491 return true;
492 }
493
494 bool CheckThrowable(ScopedObjectAccess& soa, jthrowable jobj)
Mathieu Chartier90443472015-07-16 20:32:27 -0700495 SHARED_REQUIRES(Locks::mutator_lock_) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700496 mirror::Object* obj = soa.Decode<mirror::Object*>(jobj);
497 if (!obj->GetClass()->IsThrowableClass()) {
498 AbortF("expected java.lang.Throwable but got object of type "
499 "%s: %p", PrettyTypeOf(obj).c_str(), obj);
500 return false;
501 }
502 return true;
503 }
504
505 bool CheckThrowableClass(ScopedObjectAccess& soa, jclass jc)
Mathieu Chartier90443472015-07-16 20:32:27 -0700506 SHARED_REQUIRES(Locks::mutator_lock_) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700507 mirror::Class* c = soa.Decode<mirror::Class*>(jc);
508 if (!c->IsThrowableClass()) {
509 AbortF("expected java.lang.Throwable class but got object of "
510 "type %s: %p", PrettyDescriptor(c).c_str(), c);
511 return false;
512 }
513 return true;
514 }
515
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700516 bool CheckReferenceKind(IndirectRefKind expected_kind, Thread* self, jobject obj) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700517 IndirectRefKind found_kind;
518 if (expected_kind == kLocal) {
519 found_kind = GetIndirectRefKind(obj);
520 if (found_kind == kHandleScopeOrInvalid && self->HandleScopeContains(obj)) {
521 found_kind = kLocal;
522 }
523 } else {
524 found_kind = GetIndirectRefKind(obj);
525 }
526 if (obj != nullptr && found_kind != expected_kind) {
527 AbortF("expected reference of kind %s but found %s: %p",
528 ToStr<IndirectRefKind>(expected_kind).c_str(),
529 ToStr<IndirectRefKind>(GetIndirectRefKind(obj)).c_str(),
530 obj);
531 return false;
532 }
533 return true;
534 }
535
536 bool CheckInstantiableNonArray(ScopedObjectAccess& soa, jclass jc)
Mathieu Chartier90443472015-07-16 20:32:27 -0700537 SHARED_REQUIRES(Locks::mutator_lock_) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700538 mirror::Class* c = soa.Decode<mirror::Class*>(jc);
539 if (!c->IsInstantiableNonArray()) {
540 AbortF("can't make objects of type %s: %p", PrettyDescriptor(c).c_str(), c);
541 return false;
542 }
543 return true;
544 }
545
546 bool CheckPrimitiveArrayType(ScopedObjectAccess& soa, jarray array, Primitive::Type type)
Mathieu Chartier90443472015-07-16 20:32:27 -0700547 SHARED_REQUIRES(Locks::mutator_lock_) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700548 if (!CheckArray(soa, array)) {
549 return false;
550 }
551 mirror::Array* a = soa.Decode<mirror::Array*>(array);
552 if (a->GetClass()->GetComponentType()->GetPrimitiveType() != type) {
553 AbortF("incompatible array type %s expected %s[]: %p",
554 PrettyDescriptor(a->GetClass()).c_str(), PrettyDescriptor(type).c_str(), array);
555 return false;
556 }
557 return true;
558 }
559
560 bool CheckFieldAccess(ScopedObjectAccess& soa, jobject obj, jfieldID fid, bool is_static,
561 Primitive::Type type)
Mathieu Chartier90443472015-07-16 20:32:27 -0700562 SHARED_REQUIRES(Locks::mutator_lock_) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700563 if (is_static && !CheckStaticFieldID(soa, down_cast<jclass>(obj), fid)) {
564 return false;
565 }
566 if (!is_static && !CheckInstanceFieldID(soa, obj, fid)) {
567 return false;
568 }
Mathieu Chartierc7853442015-03-27 14:35:38 -0700569 ArtField* field = soa.DecodeField(fid);
Ian Rogers68d8b422014-07-17 11:09:10 -0700570 DCHECK(field != nullptr); // Already checked by Check.
571 if (is_static != field->IsStatic()) {
572 AbortF("attempt to access %s field %s: %p",
573 field->IsStatic() ? "static" : "non-static", PrettyField(field).c_str(), fid);
574 return false;
575 }
576 if (type != field->GetTypeAsPrimitiveType()) {
577 AbortF("attempt to access field %s of type %s with the wrong type %s: %p",
578 PrettyField(field).c_str(), PrettyDescriptor(field->GetTypeDescriptor()).c_str(),
579 PrettyDescriptor(type).c_str(), fid);
580 return false;
581 }
582 if (is_static) {
583 mirror::Object* o = soa.Decode<mirror::Object*>(obj);
584 if (o == nullptr || !o->IsClass()) {
585 AbortF("attempt to access static field %s with a class argument of type %s: %p",
586 PrettyField(field).c_str(), PrettyTypeOf(o).c_str(), fid);
587 return false;
588 }
589 mirror::Class* c = o->AsClass();
590 if (field->GetDeclaringClass() != c) {
591 AbortF("attempt to access static field %s with an incompatible class argument of %s: %p",
592 PrettyField(field).c_str(), PrettyDescriptor(c).c_str(), fid);
593 return false;
594 }
595 } else {
596 mirror::Object* o = soa.Decode<mirror::Object*>(obj);
597 if (o == nullptr || !field->GetDeclaringClass()->IsAssignableFrom(o->GetClass())) {
598 AbortF("attempt to access field %s from an object argument of type %s: %p",
599 PrettyField(field).c_str(), PrettyTypeOf(o).c_str(), fid);
600 return false;
601 }
602 }
603 return true;
604 }
605
606 private:
Elliott Hughesa92853e2012-02-07 16:09:27 -0800607 enum InstanceKind {
608 kClass,
Elliott Hughes0f3c5532012-03-30 14:51:51 -0700609 kDirectByteBuffer,
610 kObject,
611 kString,
612 kThrowable,
Elliott Hughesa92853e2012-02-07 16:09:27 -0800613 };
614
615 /*
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700616 * Verify that "jobj" is a valid non-null object reference, and points to
Elliott Hughesa92853e2012-02-07 16:09:27 -0800617 * an instance of expectedClass.
618 *
619 * Because we're looking at an object on the GC heap, we have to switch
620 * to "running" mode before doing the checks.
621 */
Ian Rogers68d8b422014-07-17 11:09:10 -0700622 bool CheckInstance(ScopedObjectAccess& soa, InstanceKind kind, jobject java_object, bool null_ok)
Mathieu Chartier90443472015-07-16 20:32:27 -0700623 SHARED_REQUIRES(Locks::mutator_lock_) {
Ian Rogersef7d42f2014-01-06 12:55:46 -0800624 const char* what = nullptr;
Elliott Hughesa92853e2012-02-07 16:09:27 -0800625 switch (kind) {
626 case kClass:
627 what = "jclass";
628 break;
629 case kDirectByteBuffer:
630 what = "direct ByteBuffer";
631 break;
632 case kObject:
633 what = "jobject";
634 break;
635 case kString:
636 what = "jstring";
637 break;
638 case kThrowable:
639 what = "jthrowable";
640 break;
641 default:
Elliott Hughes7b9d9962012-04-20 18:48:18 -0700642 LOG(FATAL) << "Unknown kind " << static_cast<int>(kind);
Elliott Hughesa92853e2012-02-07 16:09:27 -0800643 }
644
Ian Rogersef7d42f2014-01-06 12:55:46 -0800645 if (java_object == nullptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700646 if (null_ok) {
647 return true;
648 } else {
649 AbortF("%s received NULL %s", function_name_, what);
650 return false;
651 }
Elliott Hughesa92853e2012-02-07 16:09:27 -0800652 }
653
Ian Rogers68d8b422014-07-17 11:09:10 -0700654 mirror::Object* obj = soa.Decode<mirror::Object*>(java_object);
Ian Rogersc0542af2014-09-03 16:16:56 -0700655 if (obj == nullptr) {
656 // Either java_object is invalid or is a cleared weak.
657 IndirectRef ref = reinterpret_cast<IndirectRef>(java_object);
658 bool okay;
659 if (GetIndirectRefKind(ref) != kWeakGlobal) {
660 okay = false;
661 } else {
662 obj = soa.Vm()->DecodeWeakGlobal(soa.Self(), ref);
663 okay = Runtime::Current()->IsClearedJniWeakGlobal(obj);
664 }
665 if (!okay) {
666 AbortF("%s is an invalid %s: %p (%p)",
667 what, ToStr<IndirectRefKind>(GetIndirectRefKind(java_object)).c_str(),
668 java_object, obj);
669 return false;
670 }
671 }
672
Mathieu Chartier590fee92013-09-13 13:46:47 -0700673 if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(obj)) {
Mathieu Chartier4c13a3f2014-07-14 14:57:16 -0700674 Runtime::Current()->GetHeap()->DumpSpaces(LOG(ERROR));
Ian Rogers68d8b422014-07-17 11:09:10 -0700675 AbortF("%s is an invalid %s: %p (%p)",
676 what, ToStr<IndirectRefKind>(GetIndirectRefKind(java_object)).c_str(),
677 java_object, obj);
Elliott Hughesa92853e2012-02-07 16:09:27 -0800678 return false;
679 }
680
681 bool okay = true;
682 switch (kind) {
683 case kClass:
684 okay = obj->IsClass();
685 break;
686 case kDirectByteBuffer:
687 UNIMPLEMENTED(FATAL);
688 break;
689 case kString:
690 okay = obj->GetClass()->IsStringClass();
691 break;
692 case kThrowable:
693 okay = obj->GetClass()->IsThrowableClass();
694 break;
695 case kObject:
696 break;
697 }
698 if (!okay) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700699 AbortF("%s has wrong type: %s", what, PrettyTypeOf(obj).c_str());
Elliott Hughesa92853e2012-02-07 16:09:27 -0800700 return false;
701 }
702
703 return true;
704 }
705
Ian Rogers68d8b422014-07-17 11:09:10 -0700706 /*
707 * Verify that the "mode" argument passed to a primitive array Release
708 * function is one of the valid values.
709 */
710 bool CheckReleaseMode(jint mode) {
711 if (mode != 0 && mode != JNI_COMMIT && mode != JNI_ABORT) {
712 AbortF("unknown value for release mode: %d", mode);
713 return false;
714 }
715 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -0700716 }
717
Ian Rogers68d8b422014-07-17 11:09:10 -0700718 bool CheckPossibleHeapValue(ScopedObjectAccess& soa, char fmt, JniValueType arg)
Mathieu Chartier90443472015-07-16 20:32:27 -0700719 SHARED_REQUIRES(Locks::mutator_lock_) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700720 switch (fmt) {
721 case 'a': // jarray
722 return CheckArray(soa, arg.a);
723 case 'c': // jclass
724 return CheckInstance(soa, kClass, arg.c, false);
725 case 'f': // jfieldID
726 return CheckFieldID(soa, arg.f) != nullptr;
727 case 'm': // jmethodID
728 return CheckMethodID(soa, arg.m) != nullptr;
729 case 'r': // release int
730 return CheckReleaseMode(arg.r);
731 case 's': // jstring
732 return CheckInstance(soa, kString, arg.s, false);
733 case 't': // jthrowable
734 return CheckInstance(soa, kThrowable, arg.t, false);
735 case 'E': // JNIEnv*
736 return CheckThread(arg.E);
737 case 'L': // jobject
738 return CheckInstance(soa, kObject, arg.L, true);
739 default:
740 return CheckNonHeapValue(fmt, arg);
741 }
742 }
743
744 bool CheckNonHeapValue(char fmt, JniValueType arg) {
745 switch (fmt) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700746 case 'p': // TODO: pointer - null or readable?
747 case 'v': // JavaVM*
748 case 'B': // jbyte
749 case 'C': // jchar
750 case 'D': // jdouble
751 case 'F': // jfloat
752 case 'I': // jint
753 case 'J': // jlong
754 case 'S': // jshort
755 break; // Ignored.
756 case 'b': // jboolean, why two? Fall-through.
757 case 'Z':
758 return CheckBoolean(arg.Z);
759 case 'u': // utf8
760 if ((flags_ & kFlag_Release) != 0) {
761 return CheckNonNull(arg.u);
762 } else {
763 bool nullable = ((flags_ & kFlag_NullableUtf) != 0);
764 return CheckUtfString(arg.u, nullable);
765 }
766 case 'w': // jobjectRefType
767 switch (arg.w) {
768 case JNIInvalidRefType:
769 case JNILocalRefType:
770 case JNIGlobalRefType:
771 case JNIWeakGlobalRefType:
772 break;
773 default:
774 AbortF("Unknown reference type");
775 return false;
776 }
777 break;
778 case 'z': // jsize
779 return CheckLengthPositive(arg.z);
780 default:
781 AbortF("unknown format specifier: '%c'", fmt);
782 return false;
783 }
784 return true;
785 }
786
787 void TracePossibleHeapValue(ScopedObjectAccess& soa, bool entry, char fmt, JniValueType arg,
788 std::string* msg)
Mathieu Chartier90443472015-07-16 20:32:27 -0700789 SHARED_REQUIRES(Locks::mutator_lock_) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700790 switch (fmt) {
791 case 'L': // jobject fall-through.
792 case 'a': // jarray fall-through.
793 case 's': // jstring fall-through.
794 case 't': // jthrowable fall-through.
795 if (arg.L == nullptr) {
796 *msg += "NULL";
797 } else {
798 StringAppendF(msg, "%p", arg.L);
799 }
800 break;
801 case 'c': { // jclass
802 jclass jc = arg.c;
803 mirror::Class* c = soa.Decode<mirror::Class*>(jc);
804 if (c == nullptr) {
805 *msg += "NULL";
Ian Rogersc0542af2014-09-03 16:16:56 -0700806 } else if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(c)) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700807 StringAppendF(msg, "INVALID POINTER:%p", jc);
808 } else if (!c->IsClass()) {
809 *msg += "INVALID NON-CLASS OBJECT OF TYPE:" + PrettyTypeOf(c);
810 } else {
811 *msg += PrettyClass(c);
812 if (!entry) {
813 StringAppendF(msg, " (%p)", jc);
814 }
815 }
816 break;
817 }
818 case 'f': { // jfieldID
819 jfieldID fid = arg.f;
Mathieu Chartierc7853442015-03-27 14:35:38 -0700820 ArtField* f = soa.DecodeField(fid);
Ian Rogers68d8b422014-07-17 11:09:10 -0700821 *msg += PrettyField(f);
822 if (!entry) {
823 StringAppendF(msg, " (%p)", fid);
824 }
825 break;
826 }
827 case 'm': { // jmethodID
828 jmethodID mid = arg.m;
Mathieu Chartiere401d142015-04-22 13:56:20 -0700829 ArtMethod* m = soa.DecodeMethod(mid);
Ian Rogers68d8b422014-07-17 11:09:10 -0700830 *msg += PrettyMethod(m);
831 if (!entry) {
832 StringAppendF(msg, " (%p)", mid);
833 }
834 break;
835 }
836 default:
837 TraceNonHeapValue(fmt, arg, msg);
838 break;
839 }
840 }
841
842 void TraceNonHeapValue(char fmt, JniValueType arg, std::string* msg) {
843 switch (fmt) {
844 case 'B': // jbyte
845 if (arg.B >= 0 && arg.B < 10) {
846 StringAppendF(msg, "%d", arg.B);
847 } else {
848 StringAppendF(msg, "%#x (%d)", arg.B, arg.B);
849 }
850 break;
851 case 'C': // jchar
852 if (arg.C < 0x7f && arg.C >= ' ') {
853 StringAppendF(msg, "U+%x ('%c')", arg.C, arg.C);
854 } else {
855 StringAppendF(msg, "U+%x", arg.C);
856 }
857 break;
858 case 'F': // jfloat
859 StringAppendF(msg, "%g", arg.F);
860 break;
861 case 'D': // jdouble
862 StringAppendF(msg, "%g", arg.D);
863 break;
864 case 'S': // jshort
865 StringAppendF(msg, "%d", arg.S);
866 break;
867 case 'i': // jint - fall-through.
868 case 'I': // jint
869 StringAppendF(msg, "%d", arg.I);
870 break;
871 case 'J': // jlong
872 StringAppendF(msg, "%" PRId64, arg.J);
873 break;
874 case 'Z': // jboolean
875 case 'b': // jboolean (JNI-style)
876 *msg += arg.b == JNI_TRUE ? "true" : "false";
877 break;
878 case 'V': // void
879 DCHECK(arg.V == nullptr);
880 *msg += "void";
881 break;
882 case 'v': // JavaVM*
883 StringAppendF(msg, "(JavaVM*)%p", arg.v);
884 break;
885 case 'E':
886 StringAppendF(msg, "(JNIEnv*)%p", arg.E);
887 break;
888 case 'z': // non-negative jsize
889 // You might expect jsize to be size_t, but it's not; it's the same as jint.
890 // We only treat this specially so we can do the non-negative check.
891 // TODO: maybe this wasn't worth it?
892 StringAppendF(msg, "%d", arg.z);
893 break;
894 case 'p': // void* ("pointer")
895 if (arg.p == nullptr) {
896 *msg += "NULL";
897 } else {
898 StringAppendF(msg, "(void*) %p", arg.p);
899 }
900 break;
901 case 'r': { // jint (release mode)
902 jint releaseMode = arg.r;
903 if (releaseMode == 0) {
904 *msg += "0";
905 } else if (releaseMode == JNI_ABORT) {
906 *msg += "JNI_ABORT";
907 } else if (releaseMode == JNI_COMMIT) {
908 *msg += "JNI_COMMIT";
909 } else {
910 StringAppendF(msg, "invalid release mode %d", releaseMode);
911 }
912 break;
913 }
914 case 'u': // const char* (Modified UTF-8)
915 if (arg.u == nullptr) {
916 *msg += "NULL";
917 } else {
918 StringAppendF(msg, "\"%s\"", arg.u);
919 }
920 break;
921 case 'w': // jobjectRefType
922 switch (arg.w) {
923 case JNIInvalidRefType:
924 *msg += "invalid reference type";
925 break;
926 case JNILocalRefType:
927 *msg += "local ref type";
928 break;
929 case JNIGlobalRefType:
930 *msg += "global ref type";
931 break;
932 case JNIWeakGlobalRefType:
933 *msg += "weak global ref type";
934 break;
935 default:
936 *msg += "unknown ref type";
937 break;
938 }
939 break;
Ian Rogers68d8b422014-07-17 11:09:10 -0700940 default:
941 LOG(FATAL) << function_name_ << ": unknown trace format specifier: '" << fmt << "'";
942 }
943 }
Elliott Hughesa2501992011-08-26 19:39:54 -0700944 /*
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700945 * Verify that "array" is non-null and points to an Array object.
Elliott Hughesa2501992011-08-26 19:39:54 -0700946 *
947 * Since we're dealing with objects, switch to "running" mode.
948 */
Ian Rogers68d8b422014-07-17 11:09:10 -0700949 bool CheckArray(ScopedObjectAccess& soa, jarray java_array)
Mathieu Chartier90443472015-07-16 20:32:27 -0700950 SHARED_REQUIRES(Locks::mutator_lock_) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700951 if (UNLIKELY(java_array == nullptr)) {
952 AbortF("jarray was NULL");
953 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -0700954 }
955
Ian Rogers68d8b422014-07-17 11:09:10 -0700956 mirror::Array* a = soa.Decode<mirror::Array*>(java_array);
957 if (UNLIKELY(!Runtime::Current()->GetHeap()->IsValidObjectAddress(a))) {
Mathieu Chartier4c13a3f2014-07-14 14:57:16 -0700958 Runtime::Current()->GetHeap()->DumpSpaces(LOG(ERROR));
Ian Rogers68d8b422014-07-17 11:09:10 -0700959 AbortF("jarray is an invalid %s: %p (%p)",
960 ToStr<IndirectRefKind>(GetIndirectRefKind(java_array)).c_str(),
961 java_array, a);
962 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -0700963 } else if (!a->IsArrayInstance()) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700964 AbortF("jarray argument has non-array type: %s", PrettyTypeOf(a).c_str());
965 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -0700966 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700967 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -0700968 }
969
Ian Rogers68d8b422014-07-17 11:09:10 -0700970 bool CheckBoolean(jboolean z) {
971 if (z != JNI_TRUE && z != JNI_FALSE) {
972 AbortF("unexpected jboolean value: %d", z);
973 return false;
974 }
975 return true;
976 }
977
978 bool CheckLengthPositive(jsize length) {
Elliott Hughesa2501992011-08-26 19:39:54 -0700979 if (length < 0) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700980 AbortF("negative jsize: %d", length);
981 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -0700982 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700983 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -0700984 }
985
Mathieu Chartierc7853442015-03-27 14:35:38 -0700986 ArtField* CheckFieldID(ScopedObjectAccess& soa, jfieldID fid)
Mathieu Chartier90443472015-07-16 20:32:27 -0700987 SHARED_REQUIRES(Locks::mutator_lock_) {
Ian Rogersef7d42f2014-01-06 12:55:46 -0800988 if (fid == nullptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700989 AbortF("jfieldID was NULL");
Ian Rogersef7d42f2014-01-06 12:55:46 -0800990 return nullptr;
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700991 }
Mathieu Chartierc7853442015-03-27 14:35:38 -0700992 ArtField* f = soa.DecodeField(fid);
993 // TODO: Better check here.
994 if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(f->GetDeclaringClass())) {
Mathieu Chartier4c13a3f2014-07-14 14:57:16 -0700995 Runtime::Current()->GetHeap()->DumpSpaces(LOG(ERROR));
Ian Rogers68d8b422014-07-17 11:09:10 -0700996 AbortF("invalid jfieldID: %p", fid);
Ian Rogersef7d42f2014-01-06 12:55:46 -0800997 return nullptr;
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700998 }
999 return f;
1000 }
1001
Mathieu Chartiere401d142015-04-22 13:56:20 -07001002 ArtMethod* CheckMethodID(ScopedObjectAccess& soa, jmethodID mid)
Mathieu Chartier90443472015-07-16 20:32:27 -07001003 SHARED_REQUIRES(Locks::mutator_lock_) {
Ian Rogersef7d42f2014-01-06 12:55:46 -08001004 if (mid == nullptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001005 AbortF("jmethodID was NULL");
Ian Rogersef7d42f2014-01-06 12:55:46 -08001006 return nullptr;
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001007 }
Mathieu Chartiere401d142015-04-22 13:56:20 -07001008 ArtMethod* m = soa.DecodeMethod(mid);
1009 // TODO: Better check here.
1010 if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(m->GetDeclaringClass())) {
Mathieu Chartier4c13a3f2014-07-14 14:57:16 -07001011 Runtime::Current()->GetHeap()->DumpSpaces(LOG(ERROR));
Ian Rogers68d8b422014-07-17 11:09:10 -07001012 AbortF("invalid jmethodID: %p", mid);
Ian Rogersef7d42f2014-01-06 12:55:46 -08001013 return nullptr;
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001014 }
1015 return m;
1016 }
1017
Mathieu Chartier90443472015-07-16 20:32:27 -07001018 bool CheckThread(JNIEnv* env) SHARED_REQUIRES(Locks::mutator_lock_) {
Elliott Hughesa2501992011-08-26 19:39:54 -07001019 Thread* self = Thread::Current();
Ian Rogersef7d42f2014-01-06 12:55:46 -08001020 if (self == nullptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001021 AbortF("a thread (tid %d) is making JNI calls without being attached", GetTid());
1022 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -07001023 }
1024
1025 // Get the *correct* JNIEnv by going through our TLS pointer.
1026 JNIEnvExt* threadEnv = self->GetJniEnv();
1027
Elliott Hughes3f6635a2012-06-19 13:37:49 -07001028 // Verify that the current thread is (a) attached and (b) associated with
1029 // this particular instance of JNIEnv.
Ian Rogers68d8b422014-07-17 11:09:10 -07001030 if (env != threadEnv) {
1031 AbortF("thread %s using JNIEnv* from thread %s",
1032 ToStr<Thread>(*self).c_str(), ToStr<Thread>(*self).c_str());
1033 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -07001034 }
1035
Elliott Hughes3f6635a2012-06-19 13:37:49 -07001036 // Verify that, if this thread previously made a critical "get" call, we
1037 // do the corresponding "release" call before we try anything else.
Ian Rogers68d8b422014-07-17 11:09:10 -07001038 switch (flags_ & kFlag_CritMask) {
Elliott Hughesa2501992011-08-26 19:39:54 -07001039 case kFlag_CritOkay: // okay to call this method
1040 break;
1041 case kFlag_CritBad: // not okay to call
1042 if (threadEnv->critical) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001043 AbortF("thread %s using JNI after critical get",
1044 ToStr<Thread>(*self).c_str());
1045 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -07001046 }
1047 break;
1048 case kFlag_CritGet: // this is a "get" call
Elliott Hughes3f6635a2012-06-19 13:37:49 -07001049 // Don't check here; we allow nested gets.
Elliott Hughesa2501992011-08-26 19:39:54 -07001050 threadEnv->critical++;
1051 break;
Brian Carlstrom7934ac22013-07-26 10:54:15 -07001052 case kFlag_CritRelease: // this is a "release" call
Elliott Hughesa2501992011-08-26 19:39:54 -07001053 threadEnv->critical--;
1054 if (threadEnv->critical < 0) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001055 AbortF("thread %s called too many critical releases",
1056 ToStr<Thread>(*self).c_str());
1057 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -07001058 }
1059 break;
1060 default:
Ian Rogers68d8b422014-07-17 11:09:10 -07001061 LOG(FATAL) << "Bad flags (internal error): " << flags_;
Elliott Hughesa2501992011-08-26 19:39:54 -07001062 }
1063
Elliott Hughes3f6635a2012-06-19 13:37:49 -07001064 // Verify that, if an exception has been raised, the native code doesn't
1065 // make any JNI calls other than the Exception* methods.
Ian Rogers68d8b422014-07-17 11:09:10 -07001066 if ((flags_ & kFlag_ExcepOkay) == 0 && self->IsExceptionPending()) {
Nicolas Geoffray14691c52015-03-05 10:40:17 +00001067 mirror::Throwable* exception = self->GetException();
1068 AbortF("JNI %s called with pending exception %s",
1069 function_name_,
1070 exception->Dump().c_str());
Ian Rogers68d8b422014-07-17 11:09:10 -07001071 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -07001072 }
Ian Rogers68d8b422014-07-17 11:09:10 -07001073 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -07001074 }
1075
Elliott Hughes3f6635a2012-06-19 13:37:49 -07001076 // Verifies that "bytes" points to valid Modified UTF-8 data.
Ian Rogers68d8b422014-07-17 11:09:10 -07001077 bool CheckUtfString(const char* bytes, bool nullable) {
Ian Rogersef7d42f2014-01-06 12:55:46 -08001078 if (bytes == nullptr) {
Elliott Hughesa2501992011-08-26 19:39:54 -07001079 if (!nullable) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001080 AbortF("non-nullable const char* was NULL");
1081 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -07001082 }
Ian Rogers68d8b422014-07-17 11:09:10 -07001083 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -07001084 }
1085
Ian Rogersef7d42f2014-01-06 12:55:46 -08001086 const char* errorKind = nullptr;
Andreas Gampeef4afe92015-07-27 21:03:25 -07001087 const uint8_t* utf8 = CheckUtfBytes(bytes, &errorKind);
Ian Rogersef7d42f2014-01-06 12:55:46 -08001088 if (errorKind != nullptr) {
Andreas Gampeef4afe92015-07-27 21:03:25 -07001089 // This is an expensive loop that will resize often, but this isn't supposed to hit in
1090 // practice anyways.
1091 std::ostringstream oss;
1092 oss << std::hex;
1093 const uint8_t* tmp = reinterpret_cast<const uint8_t*>(bytes);
1094 while (*tmp != 0) {
1095 if (tmp == utf8) {
1096 oss << "<";
1097 }
1098 oss << "0x" << std::setfill('0') << std::setw(2) << static_cast<uint32_t>(*tmp);
1099 if (tmp == utf8) {
1100 oss << '>';
1101 }
1102 tmp++;
1103 if (*tmp != 0) {
1104 oss << ' ';
1105 }
1106 }
1107
Ian Rogers68d8b422014-07-17 11:09:10 -07001108 AbortF("input is not valid Modified UTF-8: illegal %s byte %#x\n"
Andreas Gampeef4afe92015-07-27 21:03:25 -07001109 " string: '%s'\n input: '%s'", errorKind, *utf8, bytes, oss.str().c_str());
Ian Rogers68d8b422014-07-17 11:09:10 -07001110 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -07001111 }
Ian Rogers68d8b422014-07-17 11:09:10 -07001112 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -07001113 }
1114
Narayan Kamatha5afcfc2015-01-29 20:06:46 +00001115 // Checks whether |bytes| is valid modified UTF-8. We also accept 4 byte UTF
1116 // sequences in place of encoded surrogate pairs.
Andreas Gampeef4afe92015-07-27 21:03:25 -07001117 static const uint8_t* CheckUtfBytes(const char* bytes, const char** errorKind) {
Elliott Hughesa2501992011-08-26 19:39:54 -07001118 while (*bytes != '\0') {
Andreas Gampeef4afe92015-07-27 21:03:25 -07001119 const uint8_t* utf8 = reinterpret_cast<const uint8_t*>(bytes++);
Elliott Hughesa2501992011-08-26 19:39:54 -07001120 // Switch on the high four bits.
Andreas Gampeef4afe92015-07-27 21:03:25 -07001121 switch (*utf8 >> 4) {
Elliott Hughesa2501992011-08-26 19:39:54 -07001122 case 0x00:
1123 case 0x01:
1124 case 0x02:
1125 case 0x03:
1126 case 0x04:
1127 case 0x05:
1128 case 0x06:
1129 case 0x07:
1130 // Bit pattern 0xxx. No need for any extra bytes.
1131 break;
1132 case 0x08:
1133 case 0x09:
1134 case 0x0a:
1135 case 0x0b:
Narayan Kamatha5afcfc2015-01-29 20:06:46 +00001136 // Bit patterns 10xx, which are illegal start bytes.
Elliott Hughesa2501992011-08-26 19:39:54 -07001137 *errorKind = "start";
1138 return utf8;
Narayan Kamatha5afcfc2015-01-29 20:06:46 +00001139 case 0x0f:
1140 // Bit pattern 1111, which might be the start of a 4 byte sequence.
Andreas Gampeef4afe92015-07-27 21:03:25 -07001141 if ((*utf8 & 0x08) == 0) {
Narayan Kamatha5afcfc2015-01-29 20:06:46 +00001142 // Bit pattern 1111 0xxx, which is the start of a 4 byte sequence.
1143 // We consume one continuation byte here, and fall through to consume two more.
Andreas Gampeef4afe92015-07-27 21:03:25 -07001144 utf8 = reinterpret_cast<const uint8_t*>(bytes++);
1145 if ((*utf8 & 0xc0) != 0x80) {
Narayan Kamatha5afcfc2015-01-29 20:06:46 +00001146 *errorKind = "continuation";
1147 return utf8;
1148 }
1149 } else {
1150 *errorKind = "start";
1151 return utf8;
1152 }
1153
1154 // Fall through to the cases below to consume two more continuation bytes.
1155 FALLTHROUGH_INTENDED;
Elliott Hughesa2501992011-08-26 19:39:54 -07001156 case 0x0e:
1157 // Bit pattern 1110, so there are two additional bytes.
Andreas Gampeef4afe92015-07-27 21:03:25 -07001158 utf8 = reinterpret_cast<const uint8_t*>(bytes++);
1159 if ((*utf8 & 0xc0) != 0x80) {
Elliott Hughesa2501992011-08-26 19:39:54 -07001160 *errorKind = "continuation";
1161 return utf8;
1162 }
Narayan Kamatha5afcfc2015-01-29 20:06:46 +00001163
1164 // Fall through to consume one more continuation byte.
1165 FALLTHROUGH_INTENDED;
Elliott Hughesa2501992011-08-26 19:39:54 -07001166 case 0x0c:
1167 case 0x0d:
1168 // Bit pattern 110x, so there is one additional byte.
Andreas Gampeef4afe92015-07-27 21:03:25 -07001169 utf8 = reinterpret_cast<const uint8_t*>(bytes++);
1170 if ((*utf8 & 0xc0) != 0x80) {
Elliott Hughesa2501992011-08-26 19:39:54 -07001171 *errorKind = "continuation";
1172 return utf8;
1173 }
1174 break;
1175 }
1176 }
1177 return 0;
1178 }
1179
Ian Rogers68d8b422014-07-17 11:09:10 -07001180 void AbortF(const char* fmt, ...) __attribute__((__format__(__printf__, 2, 3))) {
1181 va_list args;
1182 va_start(args, fmt);
1183 Runtime::Current()->GetJavaVM()->JniAbortV(function_name_, fmt, args);
1184 va_end(args);
1185 }
1186
1187 // The name of the JNI function being checked.
1188 const char* const function_name_;
1189
1190 const int flags_;
Elliott Hughes92cb4982011-12-16 16:57:28 -08001191 int indent_;
Elliott Hughesa2501992011-08-26 19:39:54 -07001192
Ian Rogers68d8b422014-07-17 11:09:10 -07001193 const bool has_method_;
1194
Elliott Hughesa2501992011-08-26 19:39:54 -07001195 DISALLOW_COPY_AND_ASSIGN(ScopedCheck);
1196};
1197
Elliott Hughesa2501992011-08-26 19:39:54 -07001198/*
1199 * ===========================================================================
1200 * Guarded arrays
1201 * ===========================================================================
1202 */
1203
Elliott Hughesa2501992011-08-26 19:39:54 -07001204/* this gets tucked in at the start of the buffer; struct size must be even */
Ian Rogers68d8b422014-07-17 11:09:10 -07001205class GuardedCopy {
1206 public:
Elliott Hughesa2501992011-08-26 19:39:54 -07001207 /*
1208 * Create an over-sized buffer to hold the contents of "buf". Copy it in,
1209 * filling in the area around it with guard data.
Elliott Hughesa2501992011-08-26 19:39:54 -07001210 */
Mathieu Chartierb735bd92015-06-24 17:04:17 -07001211 static void* Create(void* original_buf, size_t len, bool mod_okay) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001212 const size_t new_len = LengthIncludingRedZones(len);
1213 uint8_t* const new_buf = DebugAlloc(new_len);
Elliott Hughesa2501992011-08-26 19:39:54 -07001214
Elliott Hughes3f6635a2012-06-19 13:37:49 -07001215 // If modification is not expected, grab a checksum.
Elliott Hughesa2501992011-08-26 19:39:54 -07001216 uLong adler = 0;
Ian Rogers68d8b422014-07-17 11:09:10 -07001217 if (!mod_okay) {
1218 adler = adler32(adler32(0L, Z_NULL, 0), reinterpret_cast<const Bytef*>(original_buf), len);
Elliott Hughesa2501992011-08-26 19:39:54 -07001219 }
1220
Ian Rogers68d8b422014-07-17 11:09:10 -07001221 GuardedCopy* copy = new (new_buf) GuardedCopy(original_buf, len, adler);
Elliott Hughesa2501992011-08-26 19:39:54 -07001222
Ian Rogers68d8b422014-07-17 11:09:10 -07001223 // Fill begin region with canary pattern.
1224 const size_t kStartCanaryLength = (GuardedCopy::kRedZoneSize / 2) - sizeof(GuardedCopy);
1225 for (size_t i = 0, j = 0; i < kStartCanaryLength; ++i) {
1226 const_cast<char*>(copy->StartRedZone())[i] = kCanary[j];
1227 if (kCanary[j] == '\0') {
1228 j = 0;
tony.ys_liu068361a2015-07-14 16:25:16 +08001229 } else {
1230 j++;
Ian Rogers68d8b422014-07-17 11:09:10 -07001231 }
1232 }
1233
1234 // Copy the data in; note "len" could be zero.
1235 memcpy(const_cast<uint8_t*>(copy->BufferWithinRedZones()), original_buf, len);
1236
1237 // Fill end region with canary pattern.
1238 for (size_t i = 0, j = 0; i < kEndCanaryLength; ++i) {
1239 const_cast<char*>(copy->EndRedZone())[i] = kCanary[j];
1240 if (kCanary[j] == '\0') {
1241 j = 0;
tony.ys_liu068361a2015-07-14 16:25:16 +08001242 } else {
1243 j++;
Ian Rogers68d8b422014-07-17 11:09:10 -07001244 }
1245 }
1246
1247 return const_cast<uint8_t*>(copy->BufferWithinRedZones());
Elliott Hughesa2501992011-08-26 19:39:54 -07001248 }
1249
1250 /*
Ian Rogers68d8b422014-07-17 11:09:10 -07001251 * Create a guarded copy of a primitive array. Modifications to the copied
1252 * data are allowed. Returns a pointer to the copied data.
1253 */
Mathieu Chartierb735bd92015-06-24 17:04:17 -07001254 static void* CreateGuardedPACopy(JNIEnv* env, const jarray java_array, jboolean* is_copy,
1255 void* original_ptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001256 ScopedObjectAccess soa(env);
1257
1258 mirror::Array* a = soa.Decode<mirror::Array*>(java_array);
1259 size_t component_size = a->GetClass()->GetComponentSize();
1260 size_t byte_count = a->GetLength() * component_size;
Mathieu Chartierb735bd92015-06-24 17:04:17 -07001261 void* result = Create(original_ptr, byte_count, true);
Ian Rogers68d8b422014-07-17 11:09:10 -07001262 if (is_copy != nullptr) {
1263 *is_copy = JNI_TRUE;
1264 }
1265 return result;
1266 }
1267
1268 /*
1269 * Perform the array "release" operation, which may or may not copy data
1270 * back into the managed heap, and may or may not release the underlying storage.
1271 */
Mathieu Chartierb735bd92015-06-24 17:04:17 -07001272 static void* ReleaseGuardedPACopy(const char* function_name, JNIEnv* env,
1273 jarray java_array ATTRIBUTE_UNUSED, void* embedded_buf,
1274 int mode) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001275 ScopedObjectAccess soa(env);
Ian Rogers68d8b422014-07-17 11:09:10 -07001276 if (!GuardedCopy::Check(function_name, embedded_buf, true)) {
1277 return nullptr;
1278 }
Mathieu Chartierb735bd92015-06-24 17:04:17 -07001279 GuardedCopy* const copy = FromEmbedded(embedded_buf);
1280 void* original_ptr = copy->original_ptr_;
Ian Rogers68d8b422014-07-17 11:09:10 -07001281 if (mode != JNI_ABORT) {
Mathieu Chartierb735bd92015-06-24 17:04:17 -07001282 memcpy(original_ptr, embedded_buf, copy->original_length_);
Ian Rogers68d8b422014-07-17 11:09:10 -07001283 }
1284 if (mode != JNI_COMMIT) {
Mathieu Chartierb735bd92015-06-24 17:04:17 -07001285 Destroy(embedded_buf);
Ian Rogers68d8b422014-07-17 11:09:10 -07001286 }
Mathieu Chartierb735bd92015-06-24 17:04:17 -07001287 return original_ptr;
Ian Rogers68d8b422014-07-17 11:09:10 -07001288 }
1289
1290
1291 /*
Elliott Hughesa2501992011-08-26 19:39:54 -07001292 * Free up the guard buffer, scrub it, and return the original pointer.
1293 */
Ian Rogers68d8b422014-07-17 11:09:10 -07001294 static void* Destroy(void* embedded_buf) {
1295 GuardedCopy* copy = FromEmbedded(embedded_buf);
1296 void* original_ptr = const_cast<void*>(copy->original_ptr_);
1297 size_t len = LengthIncludingRedZones(copy->original_length_);
1298 DebugFree(copy, len);
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001299 return original_ptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001300 }
1301
1302 /*
1303 * Verify the guard area and, if "modOkay" is false, that the data itself
1304 * has not been altered.
1305 *
Mathieu Chartier2cebb242015-04-21 16:50:40 -07001306 * The caller has already checked that "dataBuf" is non-null.
Elliott Hughesa2501992011-08-26 19:39:54 -07001307 */
Ian Rogers68d8b422014-07-17 11:09:10 -07001308 static bool Check(const char* function_name, const void* embedded_buf, bool mod_okay) {
1309 const GuardedCopy* copy = FromEmbedded(embedded_buf);
1310 return copy->CheckHeader(function_name, mod_okay) && copy->CheckRedZones(function_name);
Elliott Hughesa2501992011-08-26 19:39:54 -07001311 }
1312
1313 private:
Mathieu Chartierb735bd92015-06-24 17:04:17 -07001314 GuardedCopy(void* original_buf, size_t len, uLong adler) :
Ian Rogers68d8b422014-07-17 11:09:10 -07001315 magic_(kGuardMagic), adler_(adler), original_ptr_(original_buf), original_length_(len) {
1316 }
1317
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001318 static uint8_t* DebugAlloc(size_t len) {
Ian Rogersef7d42f2014-01-06 12:55:46 -08001319 void* result = mmap(nullptr, len, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON, -1, 0);
Elliott Hughesa2501992011-08-26 19:39:54 -07001320 if (result == MAP_FAILED) {
1321 PLOG(FATAL) << "GuardedCopy::create mmap(" << len << ") failed";
1322 }
1323 return reinterpret_cast<uint8_t*>(result);
1324 }
1325
Ian Rogers68d8b422014-07-17 11:09:10 -07001326 static void DebugFree(void* buf, size_t len) {
1327 if (munmap(buf, len) != 0) {
1328 PLOG(FATAL) << "munmap(" << buf << ", " << len << ") failed";
Elliott Hughesa2501992011-08-26 19:39:54 -07001329 }
1330 }
1331
Ian Rogers68d8b422014-07-17 11:09:10 -07001332 static size_t LengthIncludingRedZones(size_t len) {
1333 return len + kRedZoneSize;
Elliott Hughesa2501992011-08-26 19:39:54 -07001334 }
1335
Ian Rogers68d8b422014-07-17 11:09:10 -07001336 // Get the GuardedCopy from the interior pointer.
1337 static GuardedCopy* FromEmbedded(void* embedded_buf) {
1338 return reinterpret_cast<GuardedCopy*>(
1339 reinterpret_cast<uint8_t*>(embedded_buf) - (kRedZoneSize / 2));
Elliott Hughesa2501992011-08-26 19:39:54 -07001340 }
1341
Ian Rogers68d8b422014-07-17 11:09:10 -07001342 static const GuardedCopy* FromEmbedded(const void* embedded_buf) {
1343 return reinterpret_cast<const GuardedCopy*>(
1344 reinterpret_cast<const uint8_t*>(embedded_buf) - (kRedZoneSize / 2));
Elliott Hughesa2501992011-08-26 19:39:54 -07001345 }
Ian Rogers68d8b422014-07-17 11:09:10 -07001346
1347 static void AbortF(const char* jni_function_name, const char* fmt, ...) {
1348 va_list args;
1349 va_start(args, fmt);
1350 Runtime::Current()->GetJavaVM()->JniAbortV(jni_function_name, fmt, args);
1351 va_end(args);
1352 }
1353
1354 bool CheckHeader(const char* function_name, bool mod_okay) const {
1355 static const uint32_t kMagicCmp = kGuardMagic;
1356
1357 // Before we do anything with "pExtra", check the magic number. We
1358 // do the check with memcmp rather than "==" in case the pointer is
1359 // unaligned. If it points to completely bogus memory we're going
1360 // to crash, but there's no easy way around that.
1361 if (UNLIKELY(memcmp(&magic_, &kMagicCmp, 4) != 0)) {
1362 uint8_t buf[4];
1363 memcpy(buf, &magic_, 4);
1364 AbortF(function_name,
1365 "guard magic does not match (found 0x%02x%02x%02x%02x) -- incorrect data pointer %p?",
1366 buf[3], buf[2], buf[1], buf[0], this); // Assumes little-endian.
1367 return false;
1368 }
1369
1370 // If modification is not expected, verify checksum. Strictly speaking this is wrong: if we
1371 // told the client that we made a copy, there's no reason they can't alter the buffer.
1372 if (!mod_okay) {
1373 uLong computed_adler =
1374 adler32(adler32(0L, Z_NULL, 0), BufferWithinRedZones(), original_length_);
1375 if (computed_adler != adler_) {
1376 AbortF(function_name, "buffer modified (0x%08lx vs 0x%08lx) at address %p",
1377 computed_adler, adler_, this);
1378 return false;
1379 }
1380 }
1381 return true;
1382 }
1383
1384 bool CheckRedZones(const char* function_name) const {
1385 // Check the begin red zone.
1386 const size_t kStartCanaryLength = (GuardedCopy::kRedZoneSize / 2) - sizeof(GuardedCopy);
1387 for (size_t i = 0, j = 0; i < kStartCanaryLength; ++i) {
1388 if (UNLIKELY(StartRedZone()[i] != kCanary[j])) {
1389 AbortF(function_name, "guard pattern before buffer disturbed at %p +%zd", this, i);
1390 return false;
1391 }
1392 if (kCanary[j] == '\0') {
1393 j = 0;
tony.ys_liu068361a2015-07-14 16:25:16 +08001394 } else {
1395 j++;
Ian Rogers68d8b422014-07-17 11:09:10 -07001396 }
1397 }
1398
1399 // Check end region.
1400 for (size_t i = 0, j = 0; i < kEndCanaryLength; ++i) {
1401 if (UNLIKELY(EndRedZone()[i] != kCanary[j])) {
1402 size_t offset_from_buffer_start =
1403 &(EndRedZone()[i]) - &(StartRedZone()[kStartCanaryLength]);
1404 AbortF(function_name, "guard pattern after buffer disturbed at %p +%zd", this,
1405 offset_from_buffer_start);
1406 return false;
1407 }
1408 if (kCanary[j] == '\0') {
1409 j = 0;
tony.ys_liu068361a2015-07-14 16:25:16 +08001410 } else {
1411 j++;
Ian Rogers68d8b422014-07-17 11:09:10 -07001412 }
1413 }
1414 return true;
1415 }
1416
1417 // Location that canary value will be written before the guarded region.
1418 const char* StartRedZone() const {
1419 const uint8_t* buf = reinterpret_cast<const uint8_t*>(this);
1420 return reinterpret_cast<const char*>(buf + sizeof(GuardedCopy));
1421 }
1422
1423 // Return the interior embedded buffer.
1424 const uint8_t* BufferWithinRedZones() const {
1425 const uint8_t* embedded_buf = reinterpret_cast<const uint8_t*>(this) + (kRedZoneSize / 2);
1426 return embedded_buf;
1427 }
1428
1429 // Location that canary value will be written after the guarded region.
1430 const char* EndRedZone() const {
1431 const uint8_t* buf = reinterpret_cast<const uint8_t*>(this);
1432 size_t buf_len = LengthIncludingRedZones(original_length_);
1433 return reinterpret_cast<const char*>(buf + (buf_len - (kRedZoneSize / 2)));
1434 }
1435
1436 static constexpr size_t kRedZoneSize = 512;
1437 static constexpr size_t kEndCanaryLength = kRedZoneSize / 2;
1438
1439 // Value written before and after the guarded array.
1440 static const char* const kCanary;
1441
1442 static constexpr uint32_t kGuardMagic = 0xffd5aa96;
1443
1444 const uint32_t magic_;
1445 const uLong adler_;
Mathieu Chartierb735bd92015-06-24 17:04:17 -07001446 void* const original_ptr_;
Ian Rogers68d8b422014-07-17 11:09:10 -07001447 const size_t original_length_;
Elliott Hughesa2501992011-08-26 19:39:54 -07001448};
Ian Rogers68d8b422014-07-17 11:09:10 -07001449const char* const GuardedCopy::kCanary = "JNI BUFFER RED ZONE";
Elliott Hughesa2501992011-08-26 19:39:54 -07001450
1451/*
1452 * ===========================================================================
1453 * JNI functions
1454 * ===========================================================================
1455 */
1456
1457class CheckJNI {
1458 public:
1459 static jint GetVersion(JNIEnv* env) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001460 ScopedObjectAccess soa(env);
1461 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1462 JniValueType args[1] = {{.E = env }};
1463 if (sc.Check(soa, true, "E", args)) {
1464 JniValueType result;
1465 result.I = baseEnv(env)->GetVersion(env);
1466 if (sc.Check(soa, false, "I", &result)) {
1467 return result.I;
1468 }
1469 }
1470 return JNI_ERR;
Elliott Hughesa2501992011-08-26 19:39:54 -07001471 }
1472
Ian Rogers68d8b422014-07-17 11:09:10 -07001473 static jint GetJavaVM(JNIEnv *env, JavaVM **vm) {
1474 ScopedObjectAccess soa(env);
1475 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1476 JniValueType args[2] = {{.E = env }, {.p = vm}};
1477 if (sc.Check(soa, true, "Ep", args)) {
1478 JniValueType result;
1479 result.i = baseEnv(env)->GetJavaVM(env, vm);
1480 if (sc.Check(soa, false, "i", &result)) {
1481 return result.i;
1482 }
1483 }
1484 return JNI_ERR;
1485 }
1486
1487 static jint RegisterNatives(JNIEnv* env, jclass c, const JNINativeMethod* methods, jint nMethods) {
1488 ScopedObjectAccess soa(env);
1489 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1490 JniValueType args[4] = {{.E = env }, {.c = c}, {.p = methods}, {.I = nMethods}};
1491 if (sc.Check(soa, true, "EcpI", args)) {
1492 JniValueType result;
1493 result.i = baseEnv(env)->RegisterNatives(env, c, methods, nMethods);
1494 if (sc.Check(soa, false, "i", &result)) {
1495 return result.i;
1496 }
1497 }
1498 return JNI_ERR;
1499 }
1500
1501 static jint UnregisterNatives(JNIEnv* env, jclass c) {
1502 ScopedObjectAccess soa(env);
1503 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1504 JniValueType args[2] = {{.E = env }, {.c = c}};
1505 if (sc.Check(soa, true, "Ec", args)) {
1506 JniValueType result;
1507 result.i = baseEnv(env)->UnregisterNatives(env, c);
1508 if (sc.Check(soa, false, "i", &result)) {
1509 return result.i;
1510 }
1511 }
1512 return JNI_ERR;
1513 }
1514
1515 static jobjectRefType GetObjectRefType(JNIEnv* env, jobject obj) {
Ian Rogersc0542af2014-09-03 16:16:56 -07001516 // Note: we use "EL" here but "Ep" has been used in the past on the basis that we'd like to
1517 // know the object is invalid. The spec says that passing invalid objects or even ones that
1518 // are deleted isn't supported.
Ian Rogers68d8b422014-07-17 11:09:10 -07001519 ScopedObjectAccess soa(env);
1520 ScopedCheck sc(kFlag_Default, __FUNCTION__);
Ian Rogersc0542af2014-09-03 16:16:56 -07001521 JniValueType args[2] = {{.E = env }, {.L = obj}};
1522 if (sc.Check(soa, true, "EL", args)) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001523 JniValueType result;
1524 result.w = baseEnv(env)->GetObjectRefType(env, obj);
1525 if (sc.Check(soa, false, "w", &result)) {
1526 return result.w;
1527 }
1528 }
1529 return JNIInvalidRefType;
1530 }
1531
1532 static jclass DefineClass(JNIEnv* env, const char* name, jobject loader, const jbyte* buf,
1533 jsize bufLen) {
1534 ScopedObjectAccess soa(env);
1535 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1536 JniValueType args[5] = {{.E = env}, {.u = name}, {.L = loader}, {.p = buf}, {.z = bufLen}};
1537 if (sc.Check(soa, true, "EuLpz", args) && sc.CheckClassName(name)) {
1538 JniValueType result;
1539 result.c = baseEnv(env)->DefineClass(env, name, loader, buf, bufLen);
1540 if (sc.Check(soa, false, "c", &result)) {
1541 return result.c;
1542 }
1543 }
1544 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001545 }
1546
1547 static jclass FindClass(JNIEnv* env, const char* name) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001548 ScopedObjectAccess soa(env);
1549 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1550 JniValueType args[2] = {{.E = env}, {.u = name}};
1551 if (sc.Check(soa, true, "Eu", args) && sc.CheckClassName(name)) {
1552 JniValueType result;
1553 result.c = baseEnv(env)->FindClass(env, name);
1554 if (sc.Check(soa, false, "c", &result)) {
1555 return result.c;
1556 }
1557 }
1558 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001559 }
1560
Elliott Hughese84278b2012-03-22 10:06:53 -07001561 static jclass GetSuperclass(JNIEnv* env, jclass c) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001562 ScopedObjectAccess soa(env);
1563 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1564 JniValueType args[2] = {{.E = env}, {.c = c}};
1565 if (sc.Check(soa, true, "Ec", args)) {
1566 JniValueType result;
1567 result.c = baseEnv(env)->GetSuperclass(env, c);
1568 if (sc.Check(soa, false, "c", &result)) {
1569 return result.c;
1570 }
1571 }
1572 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001573 }
1574
Elliott Hughese84278b2012-03-22 10:06:53 -07001575 static jboolean IsAssignableFrom(JNIEnv* env, jclass c1, jclass c2) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001576 ScopedObjectAccess soa(env);
1577 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1578 JniValueType args[3] = {{.E = env}, {.c = c1}, {.c = c2}};
1579 if (sc.Check(soa, true, "Ecc", args)) {
1580 JniValueType result;
1581 result.b = baseEnv(env)->IsAssignableFrom(env, c1, c2);
1582 if (sc.Check(soa, false, "b", &result)) {
1583 return result.b;
1584 }
1585 }
1586 return JNI_FALSE;
Elliott Hughesa2501992011-08-26 19:39:54 -07001587 }
1588
1589 static jmethodID FromReflectedMethod(JNIEnv* env, jobject method) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001590 ScopedObjectAccess soa(env);
1591 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1592 JniValueType args[2] = {{.E = env}, {.L = method}};
1593 if (sc.Check(soa, true, "EL", args) && sc.CheckReflectedMethod(soa, method)) {
1594 JniValueType result;
1595 result.m = baseEnv(env)->FromReflectedMethod(env, method);
1596 if (sc.Check(soa, false, "m", &result)) {
1597 return result.m;
1598 }
1599 }
1600 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001601 }
1602
1603 static jfieldID FromReflectedField(JNIEnv* env, jobject field) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001604 ScopedObjectAccess soa(env);
1605 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1606 JniValueType args[2] = {{.E = env}, {.L = field}};
1607 if (sc.Check(soa, true, "EL", args) && sc.CheckReflectedField(soa, field)) {
1608 JniValueType result;
1609 result.f = baseEnv(env)->FromReflectedField(env, field);
1610 if (sc.Check(soa, false, "f", &result)) {
1611 return result.f;
1612 }
1613 }
1614 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001615 }
1616
1617 static jobject ToReflectedMethod(JNIEnv* env, jclass cls, jmethodID mid, jboolean isStatic) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001618 ScopedObjectAccess soa(env);
1619 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1620 JniValueType args[4] = {{.E = env}, {.c = cls}, {.m = mid}, {.b = isStatic}};
1621 if (sc.Check(soa, true, "Ecmb", args)) {
1622 JniValueType result;
1623 result.L = baseEnv(env)->ToReflectedMethod(env, cls, mid, isStatic);
1624 if (sc.Check(soa, false, "L", &result) && (result.L != nullptr)) {
1625 DCHECK(sc.CheckReflectedMethod(soa, result.L));
1626 return result.L;
1627 }
1628 }
1629 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001630 }
1631
1632 static jobject ToReflectedField(JNIEnv* env, jclass cls, jfieldID fid, jboolean isStatic) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001633 ScopedObjectAccess soa(env);
1634 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1635 JniValueType args[4] = {{.E = env}, {.c = cls}, {.f = fid}, {.b = isStatic}};
1636 if (sc.Check(soa, true, "Ecfb", args)) {
1637 JniValueType result;
1638 result.L = baseEnv(env)->ToReflectedField(env, cls, fid, isStatic);
1639 if (sc.Check(soa, false, "L", &result) && (result.L != nullptr)) {
1640 DCHECK(sc.CheckReflectedField(soa, result.L));
1641 return result.L;
1642 }
1643 }
1644 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001645 }
1646
1647 static jint Throw(JNIEnv* env, jthrowable obj) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001648 ScopedObjectAccess soa(env);
1649 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1650 JniValueType args[2] = {{.E = env}, {.t = obj}};
1651 if (sc.Check(soa, true, "Et", args) && sc.CheckThrowable(soa, obj)) {
1652 JniValueType result;
1653 result.i = baseEnv(env)->Throw(env, obj);
1654 if (sc.Check(soa, false, "i", &result)) {
1655 return result.i;
1656 }
1657 }
1658 return JNI_ERR;
Elliott Hughesa2501992011-08-26 19:39:54 -07001659 }
1660
Elliott Hughese84278b2012-03-22 10:06:53 -07001661 static jint ThrowNew(JNIEnv* env, jclass c, const char* message) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001662 ScopedObjectAccess soa(env);
1663 ScopedCheck sc(kFlag_NullableUtf, __FUNCTION__);
Christopher Ferrisc50358b2015-04-17 13:26:09 -07001664 JniValueType args[3] = {{.E = env}, {.c = c}, {.u = message}};
Ian Rogers68d8b422014-07-17 11:09:10 -07001665 if (sc.Check(soa, true, "Ecu", args) && sc.CheckThrowableClass(soa, c)) {
1666 JniValueType result;
1667 result.i = baseEnv(env)->ThrowNew(env, c, message);
1668 if (sc.Check(soa, false, "i", &result)) {
1669 return result.i;
1670 }
1671 }
1672 return JNI_ERR;
Elliott Hughesa2501992011-08-26 19:39:54 -07001673 }
1674
1675 static jthrowable ExceptionOccurred(JNIEnv* env) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001676 ScopedObjectAccess soa(env);
1677 ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__);
1678 JniValueType args[1] = {{.E = env}};
1679 if (sc.Check(soa, true, "E", args)) {
1680 JniValueType result;
1681 result.t = baseEnv(env)->ExceptionOccurred(env);
1682 if (sc.Check(soa, false, "t", &result)) {
1683 return result.t;
1684 }
1685 }
1686 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001687 }
1688
1689 static void ExceptionDescribe(JNIEnv* env) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001690 ScopedObjectAccess soa(env);
1691 ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__);
1692 JniValueType args[1] = {{.E = env}};
1693 if (sc.Check(soa, true, "E", args)) {
1694 JniValueType result;
1695 baseEnv(env)->ExceptionDescribe(env);
1696 result.V = nullptr;
1697 sc.Check(soa, false, "V", &result);
1698 }
Elliott Hughesa2501992011-08-26 19:39:54 -07001699 }
1700
1701 static void ExceptionClear(JNIEnv* env) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001702 ScopedObjectAccess soa(env);
1703 ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__);
1704 JniValueType args[1] = {{.E = env}};
1705 if (sc.Check(soa, true, "E", args)) {
1706 JniValueType result;
1707 baseEnv(env)->ExceptionClear(env);
1708 result.V = nullptr;
1709 sc.Check(soa, false, "V", &result);
1710 }
1711 }
1712
1713 static jboolean ExceptionCheck(JNIEnv* env) {
1714 ScopedObjectAccess soa(env);
1715 ScopedCheck sc(kFlag_CritOkay | kFlag_ExcepOkay, __FUNCTION__);
1716 JniValueType args[1] = {{.E = env}};
1717 if (sc.Check(soa, true, "E", args)) {
1718 JniValueType result;
1719 result.b = baseEnv(env)->ExceptionCheck(env);
1720 if (sc.Check(soa, false, "b", &result)) {
1721 return result.b;
1722 }
1723 }
1724 return JNI_FALSE;
Elliott Hughesa2501992011-08-26 19:39:54 -07001725 }
1726
1727 static void FatalError(JNIEnv* env, const char* msg) {
Elliott Hughesc4378df2013-06-14 17:05:13 -07001728 // The JNI specification doesn't say it's okay to call FatalError with a pending exception,
1729 // but you're about to abort anyway, and it's quite likely that you have a pending exception,
1730 // and it's not unimaginable that you don't know that you do. So we allow it.
Ian Rogers68d8b422014-07-17 11:09:10 -07001731 ScopedObjectAccess soa(env);
1732 ScopedCheck sc(kFlag_ExcepOkay | kFlag_NullableUtf, __FUNCTION__);
1733 JniValueType args[2] = {{.E = env}, {.u = msg}};
1734 if (sc.Check(soa, true, "Eu", args)) {
1735 JniValueType result;
1736 baseEnv(env)->FatalError(env, msg);
1737 // Unreachable.
1738 result.V = nullptr;
1739 sc.Check(soa, false, "V", &result);
1740 }
Elliott Hughesa2501992011-08-26 19:39:54 -07001741 }
1742
1743 static jint PushLocalFrame(JNIEnv* env, jint capacity) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001744 ScopedObjectAccess soa(env);
1745 ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__);
1746 JniValueType args[2] = {{.E = env}, {.I = capacity}};
1747 if (sc.Check(soa, true, "EI", args)) {
1748 JniValueType result;
1749 result.i = baseEnv(env)->PushLocalFrame(env, capacity);
1750 if (sc.Check(soa, false, "i", &result)) {
1751 return result.i;
1752 }
1753 }
1754 return JNI_ERR;
Elliott Hughesa2501992011-08-26 19:39:54 -07001755 }
1756
1757 static jobject PopLocalFrame(JNIEnv* env, jobject res) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001758 ScopedObjectAccess soa(env);
1759 ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__);
1760 JniValueType args[2] = {{.E = env}, {.L = res}};
1761 if (sc.Check(soa, true, "EL", args)) {
1762 JniValueType result;
1763 result.L = baseEnv(env)->PopLocalFrame(env, res);
1764 sc.Check(soa, false, "L", &result);
1765 return result.L;
1766 }
1767 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001768 }
1769
1770 static jobject NewGlobalRef(JNIEnv* env, jobject obj) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001771 return NewRef(__FUNCTION__, env, obj, kGlobal);
Elliott Hughesa2501992011-08-26 19:39:54 -07001772 }
1773
Ian Rogers68d8b422014-07-17 11:09:10 -07001774 static jobject NewLocalRef(JNIEnv* env, jobject obj) {
1775 return NewRef(__FUNCTION__, env, obj, kLocal);
Elliott Hughesa2501992011-08-26 19:39:54 -07001776 }
1777
1778 static jweak NewWeakGlobalRef(JNIEnv* env, jobject obj) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001779 return NewRef(__FUNCTION__, env, obj, kWeakGlobal);
Elliott Hughesa2501992011-08-26 19:39:54 -07001780 }
1781
Ian Rogers68d8b422014-07-17 11:09:10 -07001782 static void DeleteGlobalRef(JNIEnv* env, jobject obj) {
1783 DeleteRef(__FUNCTION__, env, obj, kGlobal);
Elliott Hughesa2501992011-08-26 19:39:54 -07001784 }
1785
Ian Rogers68d8b422014-07-17 11:09:10 -07001786 static void DeleteWeakGlobalRef(JNIEnv* env, jweak obj) {
1787 DeleteRef(__FUNCTION__, env, obj, kWeakGlobal);
1788 }
1789
1790 static void DeleteLocalRef(JNIEnv* env, jobject obj) {
1791 DeleteRef(__FUNCTION__, env, obj, kLocal);
1792 }
1793
1794 static jint EnsureLocalCapacity(JNIEnv *env, jint capacity) {
1795 ScopedObjectAccess soa(env);
1796 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1797 JniValueType args[2] = {{.E = env}, {.I = capacity}};
1798 if (sc.Check(soa, true, "EI", args)) {
1799 JniValueType result;
1800 result.i = baseEnv(env)->EnsureLocalCapacity(env, capacity);
1801 if (sc.Check(soa, false, "i", &result)) {
1802 return result.i;
1803 }
1804 }
1805 return JNI_ERR;
1806 }
1807
1808 static jboolean IsSameObject(JNIEnv* env, jobject ref1, jobject ref2) {
1809 ScopedObjectAccess soa(env);
1810 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1811 JniValueType args[3] = {{.E = env}, {.L = ref1}, {.L = ref2}};
1812 if (sc.Check(soa, true, "ELL", args)) {
1813 JniValueType result;
1814 result.b = baseEnv(env)->IsSameObject(env, ref1, ref2);
1815 if (sc.Check(soa, false, "b", &result)) {
1816 return result.b;
1817 }
1818 }
1819 return JNI_FALSE;
1820 }
1821
1822 static jobject AllocObject(JNIEnv* env, jclass c) {
1823 ScopedObjectAccess soa(env);
1824 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1825 JniValueType args[2] = {{.E = env}, {.c = c}};
1826 if (sc.Check(soa, true, "Ec", args) && sc.CheckInstantiableNonArray(soa, c)) {
1827 JniValueType result;
1828 result.L = baseEnv(env)->AllocObject(env, c);
1829 if (sc.Check(soa, false, "L", &result)) {
1830 return result.L;
1831 }
1832 }
1833 return nullptr;
1834 }
1835
1836 static jobject NewObjectV(JNIEnv* env, jclass c, jmethodID mid, va_list vargs) {
1837 ScopedObjectAccess soa(env);
1838 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1839 JniValueType args[3] = {{.E = env}, {.c = c}, {.m = mid}};
Christopher Ferrisc50358b2015-04-17 13:26:09 -07001840 if (sc.Check(soa, true, "Ecm", args) && sc.CheckInstantiableNonArray(soa, c) &&
Ian Rogers68d8b422014-07-17 11:09:10 -07001841 sc.CheckConstructor(soa, mid)) {
1842 JniValueType result;
1843 result.L = baseEnv(env)->NewObjectV(env, c, mid, vargs);
1844 if (sc.Check(soa, false, "L", &result)) {
1845 return result.L;
1846 }
1847 }
1848 return nullptr;
1849 }
1850
1851 static jobject NewObject(JNIEnv* env, jclass c, jmethodID mid, ...) {
1852 va_list args;
1853 va_start(args, mid);
1854 jobject result = NewObjectV(env, c, mid, args);
1855 va_end(args);
1856 return result;
1857 }
1858
1859 static jobject NewObjectA(JNIEnv* env, jclass c, jmethodID mid, jvalue* vargs) {
1860 ScopedObjectAccess soa(env);
1861 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1862 JniValueType args[3] = {{.E = env}, {.c = c}, {.m = mid}};
Christopher Ferrisc50358b2015-04-17 13:26:09 -07001863 if (sc.Check(soa, true, "Ecm", args) && sc.CheckInstantiableNonArray(soa, c) &&
Ian Rogers68d8b422014-07-17 11:09:10 -07001864 sc.CheckConstructor(soa, mid)) {
1865 JniValueType result;
1866 result.L = baseEnv(env)->NewObjectA(env, c, mid, vargs);
1867 if (sc.Check(soa, false, "L", &result)) {
1868 return result.L;
1869 }
1870 }
1871 return nullptr;
1872 }
1873
1874 static jclass GetObjectClass(JNIEnv* env, jobject obj) {
1875 ScopedObjectAccess soa(env);
1876 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1877 JniValueType args[2] = {{.E = env}, {.L = obj}};
1878 if (sc.Check(soa, true, "EL", args)) {
1879 JniValueType result;
1880 result.c = baseEnv(env)->GetObjectClass(env, obj);
1881 if (sc.Check(soa, false, "c", &result)) {
1882 return result.c;
1883 }
1884 }
1885 return nullptr;
1886 }
1887
1888 static jboolean IsInstanceOf(JNIEnv* env, jobject obj, jclass c) {
1889 ScopedObjectAccess soa(env);
1890 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1891 JniValueType args[3] = {{.E = env}, {.L = obj}, {.c = c}};
1892 if (sc.Check(soa, true, "ELc", args)) {
1893 JniValueType result;
1894 result.b = baseEnv(env)->IsInstanceOf(env, obj, c);
1895 if (sc.Check(soa, false, "b", &result)) {
1896 return result.b;
1897 }
1898 }
1899 return JNI_FALSE;
1900 }
1901
1902 static jmethodID GetMethodID(JNIEnv* env, jclass c, const char* name, const char* sig) {
1903 return GetMethodIDInternal(__FUNCTION__, env, c, name, sig, false);
1904 }
1905
1906 static jmethodID GetStaticMethodID(JNIEnv* env, jclass c, const char* name, const char* sig) {
1907 return GetMethodIDInternal(__FUNCTION__, env, c, name, sig, true);
1908 }
1909
1910 static jfieldID GetFieldID(JNIEnv* env, jclass c, const char* name, const char* sig) {
1911 return GetFieldIDInternal(__FUNCTION__, env, c, name, sig, false);
1912 }
1913
1914 static jfieldID GetStaticFieldID(JNIEnv* env, jclass c, const char* name, const char* sig) {
1915 return GetFieldIDInternal(__FUNCTION__, env, c, name, sig, true);
1916 }
1917
1918#define FIELD_ACCESSORS(jtype, name, ptype, shorty) \
1919 static jtype GetStatic##name##Field(JNIEnv* env, jclass c, jfieldID fid) { \
1920 return GetField(__FUNCTION__, env, c, fid, true, ptype).shorty; \
1921 } \
1922 \
1923 static jtype Get##name##Field(JNIEnv* env, jobject obj, jfieldID fid) { \
1924 return GetField(__FUNCTION__, env, obj, fid, false, ptype).shorty; \
1925 } \
1926 \
1927 static void SetStatic##name##Field(JNIEnv* env, jclass c, jfieldID fid, jtype v) { \
1928 JniValueType value; \
1929 value.shorty = v; \
1930 SetField(__FUNCTION__, env, c, fid, true, ptype, value); \
1931 } \
1932 \
1933 static void Set##name##Field(JNIEnv* env, jobject obj, jfieldID fid, jtype v) { \
1934 JniValueType value; \
1935 value.shorty = v; \
1936 SetField(__FUNCTION__, env, obj, fid, false, ptype, value); \
1937 }
1938
1939 FIELD_ACCESSORS(jobject, Object, Primitive::kPrimNot, L)
1940 FIELD_ACCESSORS(jboolean, Boolean, Primitive::kPrimBoolean, Z)
1941 FIELD_ACCESSORS(jbyte, Byte, Primitive::kPrimByte, B)
1942 FIELD_ACCESSORS(jchar, Char, Primitive::kPrimChar, C)
1943 FIELD_ACCESSORS(jshort, Short, Primitive::kPrimShort, S)
1944 FIELD_ACCESSORS(jint, Int, Primitive::kPrimInt, I)
1945 FIELD_ACCESSORS(jlong, Long, Primitive::kPrimLong, J)
1946 FIELD_ACCESSORS(jfloat, Float, Primitive::kPrimFloat, F)
1947 FIELD_ACCESSORS(jdouble, Double, Primitive::kPrimDouble, D)
1948#undef FIELD_ACCESSORS
1949
1950 static void CallVoidMethodA(JNIEnv* env, jobject obj, jmethodID mid, jvalue* vargs) {
1951 CallMethodA(__FUNCTION__, env, obj, nullptr, mid, vargs, Primitive::kPrimVoid, kVirtual);
1952 }
1953
1954 static void CallNonvirtualVoidMethodA(JNIEnv* env, jobject obj, jclass c, jmethodID mid,
1955 jvalue* vargs) {
1956 CallMethodA(__FUNCTION__, env, obj, c, mid, vargs, Primitive::kPrimVoid, kDirect);
1957 }
1958
1959 static void CallStaticVoidMethodA(JNIEnv* env, jclass c, jmethodID mid, jvalue* vargs) {
Marcus Oakland51be0a72014-09-24 15:23:06 +01001960 CallMethodA(__FUNCTION__, env, nullptr, c, mid, vargs, Primitive::kPrimVoid, kStatic);
Ian Rogers68d8b422014-07-17 11:09:10 -07001961 }
1962
1963 static void CallVoidMethodV(JNIEnv* env, jobject obj, jmethodID mid, va_list vargs) {
1964 CallMethodV(__FUNCTION__, env, obj, nullptr, mid, vargs, Primitive::kPrimVoid, kVirtual);
1965 }
1966
1967 static void CallNonvirtualVoidMethodV(JNIEnv* env, jobject obj, jclass c, jmethodID mid,
1968 va_list vargs) {
1969 CallMethodV(__FUNCTION__, env, obj, c, mid, vargs, Primitive::kPrimVoid, kDirect);
1970 }
1971
1972 static void CallStaticVoidMethodV(JNIEnv* env, jclass c, jmethodID mid, va_list vargs) {
1973 CallMethodV(__FUNCTION__, env, nullptr, c, mid, vargs, Primitive::kPrimVoid, kStatic);
1974 }
1975
1976 static void CallVoidMethod(JNIEnv* env, jobject obj, jmethodID mid, ...) {
1977 va_list vargs;
1978 va_start(vargs, mid);
1979 CallMethodV(__FUNCTION__, env, obj, nullptr, mid, vargs, Primitive::kPrimVoid, kVirtual);
1980 va_end(vargs);
1981 }
1982
1983 static void CallNonvirtualVoidMethod(JNIEnv* env, jobject obj, jclass c, jmethodID mid, ...) {
1984 va_list vargs;
1985 va_start(vargs, mid);
1986 CallMethodV(__FUNCTION__, env, obj, c, mid, vargs, Primitive::kPrimVoid, kDirect);
1987 va_end(vargs);
1988 }
1989
1990 static void CallStaticVoidMethod(JNIEnv* env, jclass c, jmethodID mid, ...) {
1991 va_list vargs;
1992 va_start(vargs, mid);
1993 CallMethodV(__FUNCTION__, env, nullptr, c, mid, vargs, Primitive::kPrimVoid, kStatic);
1994 va_end(vargs);
1995 }
1996
1997#define CALL(rtype, name, ptype, shorty) \
1998 static rtype Call##name##MethodA(JNIEnv* env, jobject obj, jmethodID mid, jvalue* vargs) { \
1999 return CallMethodA(__FUNCTION__, env, obj, nullptr, mid, vargs, ptype, kVirtual).shorty; \
2000 } \
2001 \
2002 static rtype CallNonvirtual##name##MethodA(JNIEnv* env, jobject obj, jclass c, jmethodID mid, \
2003 jvalue* vargs) { \
2004 return CallMethodA(__FUNCTION__, env, obj, c, mid, vargs, ptype, kDirect).shorty; \
2005 } \
2006 \
2007 static rtype CallStatic##name##MethodA(JNIEnv* env, jclass c, jmethodID mid, jvalue* vargs) { \
2008 return CallMethodA(__FUNCTION__, env, nullptr, c, mid, vargs, ptype, kStatic).shorty; \
2009 } \
2010 \
2011 static rtype Call##name##MethodV(JNIEnv* env, jobject obj, jmethodID mid, va_list vargs) { \
2012 return CallMethodV(__FUNCTION__, env, obj, nullptr, mid, vargs, ptype, kVirtual).shorty; \
2013 } \
2014 \
2015 static rtype CallNonvirtual##name##MethodV(JNIEnv* env, jobject obj, jclass c, jmethodID mid, \
2016 va_list vargs) { \
2017 return CallMethodV(__FUNCTION__, env, obj, c, mid, vargs, ptype, kDirect).shorty; \
2018 } \
2019 \
2020 static rtype CallStatic##name##MethodV(JNIEnv* env, jclass c, jmethodID mid, va_list vargs) { \
2021 return CallMethodV(__FUNCTION__, env, nullptr, c, mid, vargs, ptype, kStatic).shorty; \
2022 } \
2023 \
2024 static rtype Call##name##Method(JNIEnv* env, jobject obj, jmethodID mid, ...) { \
2025 va_list vargs; \
2026 va_start(vargs, mid); \
2027 rtype result = \
2028 CallMethodV(__FUNCTION__, env, obj, nullptr, mid, vargs, ptype, kVirtual).shorty; \
2029 va_end(vargs); \
2030 return result; \
2031 } \
2032 \
2033 static rtype CallNonvirtual##name##Method(JNIEnv* env, jobject obj, jclass c, jmethodID mid, \
2034 ...) { \
2035 va_list vargs; \
2036 va_start(vargs, mid); \
2037 rtype result = \
2038 CallMethodV(__FUNCTION__, env, obj, c, mid, vargs, ptype, kDirect).shorty; \
2039 va_end(vargs); \
2040 return result; \
2041 } \
2042 \
2043 static rtype CallStatic##name##Method(JNIEnv* env, jclass c, jmethodID mid, ...) { \
2044 va_list vargs; \
2045 va_start(vargs, mid); \
2046 rtype result = \
2047 CallMethodV(__FUNCTION__, env, nullptr, c, mid, vargs, ptype, kStatic).shorty; \
2048 va_end(vargs); \
2049 return result; \
2050 }
2051
2052 CALL(jobject, Object, Primitive::kPrimNot, L)
2053 CALL(jboolean, Boolean, Primitive::kPrimBoolean, Z)
2054 CALL(jbyte, Byte, Primitive::kPrimByte, B)
2055 CALL(jchar, Char, Primitive::kPrimChar, C)
2056 CALL(jshort, Short, Primitive::kPrimShort, S)
2057 CALL(jint, Int, Primitive::kPrimInt, I)
2058 CALL(jlong, Long, Primitive::kPrimLong, J)
2059 CALL(jfloat, Float, Primitive::kPrimFloat, F)
2060 CALL(jdouble, Double, Primitive::kPrimDouble, D)
2061#undef CALL
2062
2063 static jstring NewString(JNIEnv* env, const jchar* unicode_chars, jsize len) {
2064 ScopedObjectAccess soa(env);
2065 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2066 JniValueType args[3] = {{.E = env}, {.p = unicode_chars}, {.z = len}};
2067 if (sc.Check(soa, true, "Epz", args)) {
2068 JniValueType result;
2069 result.s = baseEnv(env)->NewString(env, unicode_chars, len);
2070 if (sc.Check(soa, false, "s", &result)) {
2071 return result.s;
2072 }
2073 }
2074 return nullptr;
2075 }
2076
2077 static jstring NewStringUTF(JNIEnv* env, const char* chars) {
2078 ScopedObjectAccess soa(env);
2079 ScopedCheck sc(kFlag_NullableUtf, __FUNCTION__);
2080 JniValueType args[2] = {{.E = env}, {.u = chars}};
2081 if (sc.Check(soa, true, "Eu", args)) {
2082 JniValueType result;
2083 // TODO: stale? show pointer and truncate string.
2084 result.s = baseEnv(env)->NewStringUTF(env, chars);
2085 if (sc.Check(soa, false, "s", &result)) {
2086 return result.s;
2087 }
2088 }
2089 return nullptr;
2090 }
2091
2092 static jsize GetStringLength(JNIEnv* env, jstring string) {
2093 ScopedObjectAccess soa(env);
2094 ScopedCheck sc(kFlag_CritOkay, __FUNCTION__);
2095 JniValueType args[2] = {{.E = env}, {.s = string}};
2096 if (sc.Check(soa, true, "Es", args)) {
2097 JniValueType result;
2098 result.z = baseEnv(env)->GetStringLength(env, string);
2099 if (sc.Check(soa, false, "z", &result)) {
2100 return result.z;
2101 }
2102 }
2103 return JNI_ERR;
2104 }
2105
2106 static jsize GetStringUTFLength(JNIEnv* env, jstring string) {
2107 ScopedObjectAccess soa(env);
2108 ScopedCheck sc(kFlag_CritOkay, __FUNCTION__);
2109 JniValueType args[2] = {{.E = env}, {.s = string}};
2110 if (sc.Check(soa, true, "Es", args)) {
2111 JniValueType result;
2112 result.z = baseEnv(env)->GetStringUTFLength(env, string);
2113 if (sc.Check(soa, false, "z", &result)) {
2114 return result.z;
2115 }
2116 }
2117 return JNI_ERR;
2118 }
2119
2120 static const jchar* GetStringChars(JNIEnv* env, jstring string, jboolean* is_copy) {
2121 return reinterpret_cast<const jchar*>(GetStringCharsInternal(__FUNCTION__, env, string,
2122 is_copy, false, false));
2123 }
2124
2125 static const char* GetStringUTFChars(JNIEnv* env, jstring string, jboolean* is_copy) {
2126 return reinterpret_cast<const char*>(GetStringCharsInternal(__FUNCTION__, env, string,
2127 is_copy, true, false));
2128 }
2129
2130 static const jchar* GetStringCritical(JNIEnv* env, jstring string, jboolean* is_copy) {
2131 return reinterpret_cast<const jchar*>(GetStringCharsInternal(__FUNCTION__, env, string,
2132 is_copy, false, true));
2133 }
2134
2135 static void ReleaseStringChars(JNIEnv* env, jstring string, const jchar* chars) {
2136 ReleaseStringCharsInternal(__FUNCTION__, env, string, chars, false, false);
2137 }
2138
2139 static void ReleaseStringUTFChars(JNIEnv* env, jstring string, const char* utf) {
2140 ReleaseStringCharsInternal(__FUNCTION__, env, string, utf, true, false);
2141 }
2142
2143 static void ReleaseStringCritical(JNIEnv* env, jstring string, const jchar* chars) {
2144 ReleaseStringCharsInternal(__FUNCTION__, env, string, chars, false, true);
2145 }
2146
2147 static void GetStringRegion(JNIEnv* env, jstring string, jsize start, jsize len, jchar* buf) {
2148 ScopedObjectAccess soa(env);
2149 ScopedCheck sc(kFlag_CritOkay, __FUNCTION__);
2150 JniValueType args[5] = {{.E = env}, {.s = string}, {.z = start}, {.z = len}, {.p = buf}};
2151 // Note: the start and len arguments are checked as 'I' rather than 'z' as invalid indices
2152 // result in ArrayIndexOutOfBoundsExceptions in the base implementation.
2153 if (sc.Check(soa, true, "EsIIp", args)) {
2154 baseEnv(env)->GetStringRegion(env, string, start, len, buf);
2155 JniValueType result;
2156 result.V = nullptr;
2157 sc.Check(soa, false, "V", &result);
2158 }
2159 }
2160
2161 static void GetStringUTFRegion(JNIEnv* env, jstring string, jsize start, jsize len, char* buf) {
2162 ScopedObjectAccess soa(env);
2163 ScopedCheck sc(kFlag_CritOkay, __FUNCTION__);
2164 JniValueType args[5] = {{.E = env}, {.s = string}, {.z = start}, {.z = len}, {.p = buf}};
2165 // Note: the start and len arguments are checked as 'I' rather than 'z' as invalid indices
2166 // result in ArrayIndexOutOfBoundsExceptions in the base implementation.
2167 if (sc.Check(soa, true, "EsIIp", args)) {
2168 baseEnv(env)->GetStringUTFRegion(env, string, start, len, buf);
2169 JniValueType result;
2170 result.V = nullptr;
2171 sc.Check(soa, false, "V", &result);
2172 }
2173 }
2174
2175 static jsize GetArrayLength(JNIEnv* env, jarray array) {
2176 ScopedObjectAccess soa(env);
2177 ScopedCheck sc(kFlag_CritOkay, __FUNCTION__);
2178 JniValueType args[2] = {{.E = env}, {.a = array}};
2179 if (sc.Check(soa, true, "Ea", args)) {
2180 JniValueType result;
2181 result.z = baseEnv(env)->GetArrayLength(env, array);
2182 if (sc.Check(soa, false, "z", &result)) {
2183 return result.z;
2184 }
2185 }
2186 return JNI_ERR;
2187 }
2188
2189 static jobjectArray NewObjectArray(JNIEnv* env, jsize length, jclass element_class,
2190 jobject initial_element) {
2191 ScopedObjectAccess soa(env);
2192 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2193 JniValueType args[4] =
2194 {{.E = env}, {.z = length}, {.c = element_class}, {.L = initial_element}};
2195 if (sc.Check(soa, true, "EzcL", args)) {
2196 JniValueType result;
2197 // Note: assignability tests of initial_element are done in the base implementation.
2198 result.a = baseEnv(env)->NewObjectArray(env, length, element_class, initial_element);
2199 if (sc.Check(soa, false, "a", &result)) {
2200 return down_cast<jobjectArray>(result.a);
2201 }
2202 }
2203 return nullptr;
2204 }
2205
2206 static jobject GetObjectArrayElement(JNIEnv* env, jobjectArray array, jsize index) {
2207 ScopedObjectAccess soa(env);
2208 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2209 JniValueType args[3] = {{.E = env}, {.a = array}, {.z = index}};
2210 if (sc.Check(soa, true, "Eaz", args)) {
2211 JniValueType result;
2212 result.L = baseEnv(env)->GetObjectArrayElement(env, array, index);
2213 if (sc.Check(soa, false, "L", &result)) {
2214 return result.L;
2215 }
2216 }
2217 return nullptr;
2218 }
2219
2220 static void SetObjectArrayElement(JNIEnv* env, jobjectArray array, jsize index, jobject value) {
2221 ScopedObjectAccess soa(env);
2222 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2223 JniValueType args[4] = {{.E = env}, {.a = array}, {.z = index}, {.L = value}};
2224 // Note: the index arguments is checked as 'I' rather than 'z' as invalid indices result in
2225 // ArrayIndexOutOfBoundsExceptions in the base implementation. Similarly invalid stores result
2226 // in ArrayStoreExceptions.
2227 if (sc.Check(soa, true, "EaIL", args)) {
2228 baseEnv(env)->SetObjectArrayElement(env, array, index, value);
2229 JniValueType result;
2230 result.V = nullptr;
2231 sc.Check(soa, false, "V", &result);
2232 }
2233 }
2234
2235 static jbooleanArray NewBooleanArray(JNIEnv* env, jsize length) {
2236 return down_cast<jbooleanArray>(NewPrimitiveArray(__FUNCTION__, env, length,
2237 Primitive::kPrimBoolean));
2238 }
2239
2240 static jbyteArray NewByteArray(JNIEnv* env, jsize length) {
2241 return down_cast<jbyteArray>(NewPrimitiveArray(__FUNCTION__, env, length,
2242 Primitive::kPrimByte));
2243 }
2244
2245 static jcharArray NewCharArray(JNIEnv* env, jsize length) {
2246 return down_cast<jcharArray>(NewPrimitiveArray(__FUNCTION__, env, length,
2247 Primitive::kPrimChar));
2248 }
2249
2250 static jshortArray NewShortArray(JNIEnv* env, jsize length) {
2251 return down_cast<jshortArray>(NewPrimitiveArray(__FUNCTION__, env, length,
2252 Primitive::kPrimShort));
2253 }
2254
2255 static jintArray NewIntArray(JNIEnv* env, jsize length) {
2256 return down_cast<jintArray>(NewPrimitiveArray(__FUNCTION__, env, length, Primitive::kPrimInt));
2257 }
2258
2259 static jlongArray NewLongArray(JNIEnv* env, jsize length) {
2260 return down_cast<jlongArray>(NewPrimitiveArray(__FUNCTION__, env, length,
2261 Primitive::kPrimLong));
2262 }
2263
2264 static jfloatArray NewFloatArray(JNIEnv* env, jsize length) {
2265 return down_cast<jfloatArray>(NewPrimitiveArray(__FUNCTION__, env, length,
2266 Primitive::kPrimFloat));
2267 }
2268
2269 static jdoubleArray NewDoubleArray(JNIEnv* env, jsize length) {
2270 return down_cast<jdoubleArray>(NewPrimitiveArray(__FUNCTION__, env, length,
2271 Primitive::kPrimDouble));
2272 }
2273
2274#define PRIMITIVE_ARRAY_FUNCTIONS(ctype, name, ptype) \
2275 static ctype* Get##name##ArrayElements(JNIEnv* env, ctype##Array array, jboolean* is_copy) { \
2276 return reinterpret_cast<ctype*>( \
2277 GetPrimitiveArrayElements(__FUNCTION__, ptype, env, array, is_copy)); \
2278 } \
2279 \
2280 static void Release##name##ArrayElements(JNIEnv* env, ctype##Array array, ctype* elems, \
2281 jint mode) { \
2282 ReleasePrimitiveArrayElements(__FUNCTION__, ptype, env, array, elems, mode); \
2283 } \
2284 \
2285 static void Get##name##ArrayRegion(JNIEnv* env, ctype##Array array, jsize start, jsize len, \
2286 ctype* buf) { \
2287 GetPrimitiveArrayRegion(__FUNCTION__, ptype, env, array, start, len, buf); \
2288 } \
2289 \
2290 static void Set##name##ArrayRegion(JNIEnv* env, ctype##Array array, jsize start, jsize len, \
2291 const ctype* buf) { \
2292 SetPrimitiveArrayRegion(__FUNCTION__, ptype, env, array, start, len, buf); \
2293 }
2294
2295 PRIMITIVE_ARRAY_FUNCTIONS(jboolean, Boolean, Primitive::kPrimBoolean)
2296 PRIMITIVE_ARRAY_FUNCTIONS(jbyte, Byte, Primitive::kPrimByte)
2297 PRIMITIVE_ARRAY_FUNCTIONS(jchar, Char, Primitive::kPrimChar)
2298 PRIMITIVE_ARRAY_FUNCTIONS(jshort, Short, Primitive::kPrimShort)
2299 PRIMITIVE_ARRAY_FUNCTIONS(jint, Int, Primitive::kPrimInt)
2300 PRIMITIVE_ARRAY_FUNCTIONS(jlong, Long, Primitive::kPrimLong)
2301 PRIMITIVE_ARRAY_FUNCTIONS(jfloat, Float, Primitive::kPrimFloat)
2302 PRIMITIVE_ARRAY_FUNCTIONS(jdouble, Double, Primitive::kPrimDouble)
2303#undef PRIMITIVE_ARRAY_FUNCTIONS
2304
2305 static jint MonitorEnter(JNIEnv* env, jobject obj) {
2306 ScopedObjectAccess soa(env);
2307 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2308 JniValueType args[2] = {{.E = env}, {.L = obj}};
2309 if (sc.Check(soa, true, "EL", args)) {
2310 JniValueType result;
2311 result.i = baseEnv(env)->MonitorEnter(env, obj);
2312 if (sc.Check(soa, false, "i", &result)) {
2313 return result.i;
2314 }
2315 }
2316 return JNI_ERR;
2317 }
2318
2319 static jint MonitorExit(JNIEnv* env, jobject obj) {
2320 ScopedObjectAccess soa(env);
2321 ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__);
2322 JniValueType args[2] = {{.E = env}, {.L = obj}};
2323 if (sc.Check(soa, true, "EL", args)) {
2324 JniValueType result;
2325 result.i = baseEnv(env)->MonitorExit(env, obj);
2326 if (sc.Check(soa, false, "i", &result)) {
2327 return result.i;
2328 }
2329 }
2330 return JNI_ERR;
2331 }
2332
2333 static void* GetPrimitiveArrayCritical(JNIEnv* env, jarray array, jboolean* is_copy) {
2334 ScopedObjectAccess soa(env);
2335 ScopedCheck sc(kFlag_CritGet, __FUNCTION__);
2336 JniValueType args[3] = {{.E = env}, {.a = array}, {.p = is_copy}};
2337 if (sc.Check(soa, true, "Eap", args)) {
2338 JniValueType result;
Mathieu Chartierb735bd92015-06-24 17:04:17 -07002339 void* ptr = baseEnv(env)->GetPrimitiveArrayCritical(env, array, is_copy);
2340 if (ptr != nullptr && soa.ForceCopy()) {
2341 ptr = GuardedCopy::CreateGuardedPACopy(env, array, is_copy, ptr);
Ian Rogers68d8b422014-07-17 11:09:10 -07002342 }
Mathieu Chartierb735bd92015-06-24 17:04:17 -07002343 result.p = ptr;
Ian Rogers68d8b422014-07-17 11:09:10 -07002344 if (sc.Check(soa, false, "p", &result)) {
2345 return const_cast<void*>(result.p);
2346 }
2347 }
2348 return nullptr;
2349 }
2350
2351 static void ReleasePrimitiveArrayCritical(JNIEnv* env, jarray array, void* carray, jint mode) {
2352 ScopedObjectAccess soa(env);
2353 ScopedCheck sc(kFlag_CritRelease | kFlag_ExcepOkay, __FUNCTION__);
2354 sc.CheckNonNull(carray);
2355 JniValueType args[4] = {{.E = env}, {.a = array}, {.p = carray}, {.r = mode}};
2356 if (sc.Check(soa, true, "Eapr", args)) {
2357 if (soa.ForceCopy()) {
Mathieu Chartierb735bd92015-06-24 17:04:17 -07002358 carray = GuardedCopy::ReleaseGuardedPACopy(__FUNCTION__, env, array, carray, mode);
Ian Rogers68d8b422014-07-17 11:09:10 -07002359 }
2360 baseEnv(env)->ReleasePrimitiveArrayCritical(env, array, carray, mode);
2361 JniValueType result;
2362 result.V = nullptr;
2363 sc.Check(soa, false, "V", &result);
2364 }
Elliott Hughesa2501992011-08-26 19:39:54 -07002365 }
2366
2367 static jobject NewDirectByteBuffer(JNIEnv* env, void* address, jlong capacity) {
Ian Rogers68d8b422014-07-17 11:09:10 -07002368 ScopedObjectAccess soa(env);
2369 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2370 JniValueType args[3] = {{.E = env}, {.p = address}, {.J = capacity}};
2371 if (sc.Check(soa, true, "EpJ", args)) {
2372 JniValueType result;
2373 // Note: the validity of address and capacity are checked in the base implementation.
2374 result.L = baseEnv(env)->NewDirectByteBuffer(env, address, capacity);
2375 if (sc.Check(soa, false, "L", &result)) {
2376 return result.L;
2377 }
Elliott Hughesa2501992011-08-26 19:39:54 -07002378 }
Ian Rogers68d8b422014-07-17 11:09:10 -07002379 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07002380 }
2381
2382 static void* GetDirectBufferAddress(JNIEnv* env, jobject buf) {
Ian Rogers68d8b422014-07-17 11:09:10 -07002383 ScopedObjectAccess soa(env);
2384 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2385 JniValueType args[2] = {{.E = env}, {.L = buf}};
2386 if (sc.Check(soa, true, "EL", args)) {
2387 JniValueType result;
2388 // Note: this is implemented in the base environment by a GetLongField which will sanity
2389 // check the type of buf in GetLongField above.
2390 result.p = baseEnv(env)->GetDirectBufferAddress(env, buf);
2391 if (sc.Check(soa, false, "p", &result)) {
2392 return const_cast<void*>(result.p);
2393 }
2394 }
2395 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07002396 }
2397
2398 static jlong GetDirectBufferCapacity(JNIEnv* env, jobject buf) {
Ian Rogers68d8b422014-07-17 11:09:10 -07002399 ScopedObjectAccess soa(env);
2400 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2401 JniValueType args[2] = {{.E = env}, {.L = buf}};
2402 if (sc.Check(soa, true, "EL", args)) {
2403 JniValueType result;
2404 // Note: this is implemented in the base environment by a GetIntField which will sanity
2405 // check the type of buf in GetIntField above.
2406 result.J = baseEnv(env)->GetDirectBufferCapacity(env, buf);
2407 if (sc.Check(soa, false, "J", &result)) {
2408 return result.J;
2409 }
2410 }
2411 return JNI_ERR;
Elliott Hughesa2501992011-08-26 19:39:54 -07002412 }
2413
2414 private:
Ian Rogers68d8b422014-07-17 11:09:10 -07002415 static JavaVMExt* GetJavaVMExt(JNIEnv* env) {
2416 return reinterpret_cast<JNIEnvExt*>(env)->vm;
2417 }
2418
2419 static const JNINativeInterface* baseEnv(JNIEnv* env) {
Elliott Hughesa2501992011-08-26 19:39:54 -07002420 return reinterpret_cast<JNIEnvExt*>(env)->unchecked_functions;
2421 }
Ian Rogers68d8b422014-07-17 11:09:10 -07002422
2423 static jobject NewRef(const char* function_name, JNIEnv* env, jobject obj, IndirectRefKind kind) {
2424 ScopedObjectAccess soa(env);
2425 ScopedCheck sc(kFlag_Default, function_name);
2426 JniValueType args[2] = {{.E = env}, {.L = obj}};
2427 if (sc.Check(soa, true, "EL", args)) {
2428 JniValueType result;
2429 switch (kind) {
2430 case kGlobal:
2431 result.L = baseEnv(env)->NewGlobalRef(env, obj);
2432 break;
2433 case kLocal:
2434 result.L = baseEnv(env)->NewLocalRef(env, obj);
2435 break;
2436 case kWeakGlobal:
2437 result.L = baseEnv(env)->NewWeakGlobalRef(env, obj);
2438 break;
2439 default:
2440 LOG(FATAL) << "Unexpected reference kind: " << kind;
2441 }
2442 if (sc.Check(soa, false, "L", &result)) {
2443 DCHECK_EQ(IsSameObject(env, obj, result.L), JNI_TRUE);
Ian Rogers6a3c1fc2014-10-31 00:33:20 -07002444 DCHECK(sc.CheckReferenceKind(kind, soa.Self(), result.L));
Ian Rogers68d8b422014-07-17 11:09:10 -07002445 return result.L;
2446 }
2447 }
2448 return nullptr;
2449 }
2450
2451 static void DeleteRef(const char* function_name, JNIEnv* env, jobject obj, IndirectRefKind kind) {
2452 ScopedObjectAccess soa(env);
2453 ScopedCheck sc(kFlag_ExcepOkay, function_name);
2454 JniValueType args[2] = {{.E = env}, {.L = obj}};
2455 sc.Check(soa, true, "EL", args);
Ian Rogers6a3c1fc2014-10-31 00:33:20 -07002456 if (sc.CheckReferenceKind(kind, soa.Self(), obj)) {
Ian Rogers68d8b422014-07-17 11:09:10 -07002457 JniValueType result;
2458 switch (kind) {
2459 case kGlobal:
2460 baseEnv(env)->DeleteGlobalRef(env, obj);
2461 break;
2462 case kLocal:
2463 baseEnv(env)->DeleteLocalRef(env, obj);
2464 break;
2465 case kWeakGlobal:
2466 baseEnv(env)->DeleteWeakGlobalRef(env, obj);
2467 break;
2468 default:
2469 LOG(FATAL) << "Unexpected reference kind: " << kind;
2470 }
2471 result.V = nullptr;
2472 sc.Check(soa, false, "V", &result);
2473 }
2474 }
2475
2476 static jmethodID GetMethodIDInternal(const char* function_name, JNIEnv* env, jclass c,
2477 const char* name, const char* sig, bool is_static) {
2478 ScopedObjectAccess soa(env);
2479 ScopedCheck sc(kFlag_Default, function_name);
2480 JniValueType args[4] = {{.E = env}, {.c = c}, {.u = name}, {.u = sig}};
2481 if (sc.Check(soa, true, "Ecuu", args)) {
2482 JniValueType result;
2483 if (is_static) {
2484 result.m = baseEnv(env)->GetStaticMethodID(env, c, name, sig);
2485 } else {
2486 result.m = baseEnv(env)->GetMethodID(env, c, name, sig);
2487 }
2488 if (sc.Check(soa, false, "m", &result)) {
2489 return result.m;
2490 }
2491 }
2492 return nullptr;
2493 }
2494
2495 static jfieldID GetFieldIDInternal(const char* function_name, JNIEnv* env, jclass c,
2496 const char* name, const char* sig, bool is_static) {
2497 ScopedObjectAccess soa(env);
2498 ScopedCheck sc(kFlag_Default, function_name);
2499 JniValueType args[4] = {{.E = env}, {.c = c}, {.u = name}, {.u = sig}};
2500 if (sc.Check(soa, true, "Ecuu", args)) {
2501 JniValueType result;
2502 if (is_static) {
2503 result.f = baseEnv(env)->GetStaticFieldID(env, c, name, sig);
2504 } else {
2505 result.f = baseEnv(env)->GetFieldID(env, c, name, sig);
2506 }
2507 if (sc.Check(soa, false, "f", &result)) {
2508 return result.f;
2509 }
2510 }
2511 return nullptr;
2512 }
2513
2514 static JniValueType GetField(const char* function_name, JNIEnv* env, jobject obj, jfieldID fid,
2515 bool is_static, Primitive::Type type) {
2516 ScopedObjectAccess soa(env);
2517 ScopedCheck sc(kFlag_Default, function_name);
2518 JniValueType args[3] = {{.E = env}, {.L = obj}, {.f = fid}};
2519 JniValueType result;
2520 if (sc.Check(soa, true, is_static ? "Ecf" : "ELf", args) &&
2521 sc.CheckFieldAccess(soa, obj, fid, is_static, type)) {
2522 const char* result_check = nullptr;
2523 switch (type) {
2524 case Primitive::kPrimNot:
2525 if (is_static) {
2526 result.L = baseEnv(env)->GetStaticObjectField(env, down_cast<jclass>(obj), fid);
2527 } else {
2528 result.L = baseEnv(env)->GetObjectField(env, obj, fid);
2529 }
2530 result_check = "L";
2531 break;
2532 case Primitive::kPrimBoolean:
2533 if (is_static) {
2534 result.Z = baseEnv(env)->GetStaticBooleanField(env, down_cast<jclass>(obj), fid);
2535 } else {
2536 result.Z = baseEnv(env)->GetBooleanField(env, obj, fid);
2537 }
2538 result_check = "Z";
2539 break;
2540 case Primitive::kPrimByte:
2541 if (is_static) {
2542 result.B = baseEnv(env)->GetStaticByteField(env, down_cast<jclass>(obj), fid);
2543 } else {
2544 result.B = baseEnv(env)->GetByteField(env, obj, fid);
2545 }
2546 result_check = "B";
2547 break;
2548 case Primitive::kPrimChar:
2549 if (is_static) {
2550 result.C = baseEnv(env)->GetStaticCharField(env, down_cast<jclass>(obj), fid);
2551 } else {
2552 result.C = baseEnv(env)->GetCharField(env, obj, fid);
2553 }
2554 result_check = "C";
2555 break;
2556 case Primitive::kPrimShort:
2557 if (is_static) {
2558 result.S = baseEnv(env)->GetStaticShortField(env, down_cast<jclass>(obj), fid);
2559 } else {
2560 result.S = baseEnv(env)->GetShortField(env, obj, fid);
2561 }
2562 result_check = "S";
2563 break;
2564 case Primitive::kPrimInt:
2565 if (is_static) {
2566 result.I = baseEnv(env)->GetStaticIntField(env, down_cast<jclass>(obj), fid);
2567 } else {
2568 result.I = baseEnv(env)->GetIntField(env, obj, fid);
2569 }
2570 result_check = "I";
2571 break;
2572 case Primitive::kPrimLong:
2573 if (is_static) {
2574 result.J = baseEnv(env)->GetStaticLongField(env, down_cast<jclass>(obj), fid);
2575 } else {
2576 result.J = baseEnv(env)->GetLongField(env, obj, fid);
2577 }
2578 result_check = "J";
2579 break;
2580 case Primitive::kPrimFloat:
2581 if (is_static) {
2582 result.F = baseEnv(env)->GetStaticFloatField(env, down_cast<jclass>(obj), fid);
2583 } else {
2584 result.F = baseEnv(env)->GetFloatField(env, obj, fid);
2585 }
2586 result_check = "F";
2587 break;
2588 case Primitive::kPrimDouble:
2589 if (is_static) {
2590 result.D = baseEnv(env)->GetStaticDoubleField(env, down_cast<jclass>(obj), fid);
2591 } else {
2592 result.D = baseEnv(env)->GetDoubleField(env, obj, fid);
2593 }
2594 result_check = "D";
2595 break;
2596 case Primitive::kPrimVoid:
2597 LOG(FATAL) << "Unexpected type: " << type;
2598 break;
2599 }
2600 if (sc.Check(soa, false, result_check, &result)) {
2601 return result;
2602 }
2603 }
2604 result.J = 0;
2605 return result;
2606 }
2607
2608 static void SetField(const char* function_name, JNIEnv* env, jobject obj, jfieldID fid,
2609 bool is_static, Primitive::Type type, JniValueType value) {
2610 ScopedObjectAccess soa(env);
2611 ScopedCheck sc(kFlag_Default, function_name);
2612 JniValueType args[4] = {{.E = env}, {.L = obj}, {.f = fid}, value};
2613 char sig[5] = { 'E', is_static ? 'c' : 'L', 'f',
2614 type == Primitive::kPrimNot ? 'L' : Primitive::Descriptor(type)[0], '\0'};
2615 if (sc.Check(soa, true, sig, args) &&
2616 sc.CheckFieldAccess(soa, obj, fid, is_static, type)) {
2617 switch (type) {
2618 case Primitive::kPrimNot:
2619 if (is_static) {
2620 baseEnv(env)->SetStaticObjectField(env, down_cast<jclass>(obj), fid, value.L);
2621 } else {
2622 baseEnv(env)->SetObjectField(env, obj, fid, value.L);
2623 }
2624 break;
2625 case Primitive::kPrimBoolean:
2626 if (is_static) {
2627 baseEnv(env)->SetStaticBooleanField(env, down_cast<jclass>(obj), fid, value.Z);
2628 } else {
2629 baseEnv(env)->SetBooleanField(env, obj, fid, value.Z);
2630 }
2631 break;
2632 case Primitive::kPrimByte:
2633 if (is_static) {
2634 baseEnv(env)->SetStaticByteField(env, down_cast<jclass>(obj), fid, value.B);
2635 } else {
2636 baseEnv(env)->SetByteField(env, obj, fid, value.B);
2637 }
2638 break;
2639 case Primitive::kPrimChar:
2640 if (is_static) {
2641 baseEnv(env)->SetStaticCharField(env, down_cast<jclass>(obj), fid, value.C);
2642 } else {
2643 baseEnv(env)->SetCharField(env, obj, fid, value.C);
2644 }
2645 break;
2646 case Primitive::kPrimShort:
2647 if (is_static) {
2648 baseEnv(env)->SetStaticShortField(env, down_cast<jclass>(obj), fid, value.S);
2649 } else {
2650 baseEnv(env)->SetShortField(env, obj, fid, value.S);
2651 }
2652 break;
2653 case Primitive::kPrimInt:
2654 if (is_static) {
2655 baseEnv(env)->SetStaticIntField(env, down_cast<jclass>(obj), fid, value.I);
2656 } else {
2657 baseEnv(env)->SetIntField(env, obj, fid, value.I);
2658 }
2659 break;
2660 case Primitive::kPrimLong:
2661 if (is_static) {
2662 baseEnv(env)->SetStaticLongField(env, down_cast<jclass>(obj), fid, value.J);
2663 } else {
2664 baseEnv(env)->SetLongField(env, obj, fid, value.J);
2665 }
2666 break;
2667 case Primitive::kPrimFloat:
2668 if (is_static) {
2669 baseEnv(env)->SetStaticFloatField(env, down_cast<jclass>(obj), fid, value.F);
2670 } else {
2671 baseEnv(env)->SetFloatField(env, obj, fid, value.F);
2672 }
2673 break;
2674 case Primitive::kPrimDouble:
2675 if (is_static) {
2676 baseEnv(env)->SetStaticDoubleField(env, down_cast<jclass>(obj), fid, value.D);
2677 } else {
2678 baseEnv(env)->SetDoubleField(env, obj, fid, value.D);
2679 }
2680 break;
2681 case Primitive::kPrimVoid:
2682 LOG(FATAL) << "Unexpected type: " << type;
2683 break;
2684 }
2685 JniValueType result;
2686 result.V = nullptr;
2687 sc.Check(soa, false, "V", &result);
2688 }
2689 }
2690
2691 static bool CheckCallArgs(ScopedObjectAccess& soa, ScopedCheck& sc, JNIEnv* env, jobject obj,
2692 jclass c, jmethodID mid, InvokeType invoke)
Mathieu Chartier90443472015-07-16 20:32:27 -07002693 SHARED_REQUIRES(Locks::mutator_lock_) {
Ian Rogers68d8b422014-07-17 11:09:10 -07002694 bool checked;
2695 switch (invoke) {
2696 case kVirtual: {
2697 DCHECK(c == nullptr);
2698 JniValueType args[3] = {{.E = env}, {.L = obj}, {.m = mid}};
Christopher Ferrisc50358b2015-04-17 13:26:09 -07002699 checked = sc.Check(soa, true, "ELm", args);
Ian Rogers68d8b422014-07-17 11:09:10 -07002700 break;
2701 }
2702 case kDirect: {
2703 JniValueType args[4] = {{.E = env}, {.L = obj}, {.c = c}, {.m = mid}};
Christopher Ferrisc50358b2015-04-17 13:26:09 -07002704 checked = sc.Check(soa, true, "ELcm", args);
Ian Rogers68d8b422014-07-17 11:09:10 -07002705 break;
2706 }
2707 case kStatic: {
2708 DCHECK(obj == nullptr);
2709 JniValueType args[3] = {{.E = env}, {.c = c}, {.m = mid}};
Christopher Ferrisc50358b2015-04-17 13:26:09 -07002710 checked = sc.Check(soa, true, "Ecm", args);
Ian Rogers68d8b422014-07-17 11:09:10 -07002711 break;
2712 }
2713 default:
2714 LOG(FATAL) << "Unexpected invoke: " << invoke;
2715 checked = false;
2716 break;
2717 }
2718 return checked;
2719 }
2720
2721 static JniValueType CallMethodA(const char* function_name, JNIEnv* env, jobject obj, jclass c,
2722 jmethodID mid, jvalue* vargs, Primitive::Type type,
2723 InvokeType invoke) {
2724 ScopedObjectAccess soa(env);
2725 ScopedCheck sc(kFlag_Default, function_name);
2726 JniValueType result;
2727 if (CheckCallArgs(soa, sc, env, obj, c, mid, invoke) &&
2728 sc.CheckMethodAndSig(soa, obj, c, mid, type, invoke)) {
2729 const char* result_check;
2730 switch (type) {
2731 case Primitive::kPrimNot:
2732 result_check = "L";
2733 switch (invoke) {
2734 case kVirtual:
2735 result.L = baseEnv(env)->CallObjectMethodA(env, obj, mid, vargs);
2736 break;
2737 case kDirect:
2738 result.L = baseEnv(env)->CallNonvirtualObjectMethodA(env, obj, c, mid, vargs);
2739 break;
2740 case kStatic:
2741 result.L = baseEnv(env)->CallStaticObjectMethodA(env, c, mid, vargs);
2742 break;
2743 default:
2744 break;
2745 }
2746 break;
2747 case Primitive::kPrimBoolean:
2748 result_check = "Z";
2749 switch (invoke) {
2750 case kVirtual:
2751 result.Z = baseEnv(env)->CallBooleanMethodA(env, obj, mid, vargs);
2752 break;
2753 case kDirect:
2754 result.Z = baseEnv(env)->CallNonvirtualBooleanMethodA(env, obj, c, mid, vargs);
2755 break;
2756 case kStatic:
2757 result.Z = baseEnv(env)->CallStaticBooleanMethodA(env, c, mid, vargs);
2758 break;
2759 default:
2760 break;
2761 }
2762 break;
2763 case Primitive::kPrimByte:
2764 result_check = "B";
2765 switch (invoke) {
2766 case kVirtual:
2767 result.B = baseEnv(env)->CallByteMethodA(env, obj, mid, vargs);
2768 break;
2769 case kDirect:
2770 result.B = baseEnv(env)->CallNonvirtualByteMethodA(env, obj, c, mid, vargs);
2771 break;
2772 case kStatic:
2773 result.B = baseEnv(env)->CallStaticByteMethodA(env, c, mid, vargs);
2774 break;
2775 default:
2776 break;
2777 }
2778 break;
2779 case Primitive::kPrimChar:
2780 result_check = "C";
2781 switch (invoke) {
2782 case kVirtual:
2783 result.C = baseEnv(env)->CallCharMethodA(env, obj, mid, vargs);
2784 break;
2785 case kDirect:
2786 result.C = baseEnv(env)->CallNonvirtualCharMethodA(env, obj, c, mid, vargs);
2787 break;
2788 case kStatic:
2789 result.C = baseEnv(env)->CallStaticCharMethodA(env, c, mid, vargs);
2790 break;
2791 default:
2792 break;
2793 }
2794 break;
2795 case Primitive::kPrimShort:
2796 result_check = "S";
2797 switch (invoke) {
2798 case kVirtual:
2799 result.S = baseEnv(env)->CallShortMethodA(env, obj, mid, vargs);
2800 break;
2801 case kDirect:
2802 result.S = baseEnv(env)->CallNonvirtualShortMethodA(env, obj, c, mid, vargs);
2803 break;
2804 case kStatic:
2805 result.S = baseEnv(env)->CallStaticShortMethodA(env, c, mid, vargs);
2806 break;
2807 default:
2808 break;
2809 }
2810 break;
2811 case Primitive::kPrimInt:
2812 result_check = "I";
2813 switch (invoke) {
2814 case kVirtual:
2815 result.I = baseEnv(env)->CallIntMethodA(env, obj, mid, vargs);
2816 break;
2817 case kDirect:
2818 result.I = baseEnv(env)->CallNonvirtualIntMethodA(env, obj, c, mid, vargs);
2819 break;
2820 case kStatic:
2821 result.I = baseEnv(env)->CallStaticIntMethodA(env, c, mid, vargs);
2822 break;
2823 default:
2824 break;
2825 }
2826 break;
2827 case Primitive::kPrimLong:
2828 result_check = "J";
2829 switch (invoke) {
2830 case kVirtual:
2831 result.J = baseEnv(env)->CallLongMethodA(env, obj, mid, vargs);
2832 break;
2833 case kDirect:
2834 result.J = baseEnv(env)->CallNonvirtualLongMethodA(env, obj, c, mid, vargs);
2835 break;
2836 case kStatic:
2837 result.J = baseEnv(env)->CallStaticLongMethodA(env, c, mid, vargs);
2838 break;
2839 default:
2840 break;
2841 }
2842 break;
2843 case Primitive::kPrimFloat:
2844 result_check = "F";
2845 switch (invoke) {
2846 case kVirtual:
2847 result.F = baseEnv(env)->CallFloatMethodA(env, obj, mid, vargs);
2848 break;
2849 case kDirect:
2850 result.F = baseEnv(env)->CallNonvirtualFloatMethodA(env, obj, c, mid, vargs);
2851 break;
2852 case kStatic:
2853 result.F = baseEnv(env)->CallStaticFloatMethodA(env, c, mid, vargs);
2854 break;
2855 default:
2856 break;
2857 }
2858 break;
2859 case Primitive::kPrimDouble:
2860 result_check = "D";
2861 switch (invoke) {
2862 case kVirtual:
2863 result.D = baseEnv(env)->CallDoubleMethodA(env, obj, mid, vargs);
2864 break;
2865 case kDirect:
2866 result.D = baseEnv(env)->CallNonvirtualDoubleMethodA(env, obj, c, mid, vargs);
2867 break;
2868 case kStatic:
2869 result.D = baseEnv(env)->CallStaticDoubleMethodA(env, c, mid, vargs);
2870 break;
2871 default:
2872 break;
2873 }
2874 break;
2875 case Primitive::kPrimVoid:
2876 result_check = "V";
2877 result.V = nullptr;
2878 switch (invoke) {
2879 case kVirtual:
2880 baseEnv(env)->CallVoidMethodA(env, obj, mid, vargs);
2881 break;
2882 case kDirect:
2883 baseEnv(env)->CallNonvirtualVoidMethodA(env, obj, c, mid, vargs);
2884 break;
2885 case kStatic:
2886 baseEnv(env)->CallStaticVoidMethodA(env, c, mid, vargs);
2887 break;
2888 default:
2889 LOG(FATAL) << "Unexpected invoke: " << invoke;
2890 }
2891 break;
2892 default:
2893 LOG(FATAL) << "Unexpected return type: " << type;
2894 result_check = nullptr;
2895 }
2896 if (sc.Check(soa, false, result_check, &result)) {
2897 return result;
2898 }
2899 }
2900 result.J = 0;
2901 return result;
2902 }
2903
2904 static JniValueType CallMethodV(const char* function_name, JNIEnv* env, jobject obj, jclass c,
2905 jmethodID mid, va_list vargs, Primitive::Type type,
2906 InvokeType invoke) {
2907 ScopedObjectAccess soa(env);
2908 ScopedCheck sc(kFlag_Default, function_name);
2909 JniValueType result;
2910 if (CheckCallArgs(soa, sc, env, obj, c, mid, invoke) &&
2911 sc.CheckMethodAndSig(soa, obj, c, mid, type, invoke)) {
2912 const char* result_check;
2913 switch (type) {
2914 case Primitive::kPrimNot:
2915 result_check = "L";
2916 switch (invoke) {
2917 case kVirtual:
2918 result.L = baseEnv(env)->CallObjectMethodV(env, obj, mid, vargs);
2919 break;
2920 case kDirect:
2921 result.L = baseEnv(env)->CallNonvirtualObjectMethodV(env, obj, c, mid, vargs);
2922 break;
2923 case kStatic:
2924 result.L = baseEnv(env)->CallStaticObjectMethodV(env, c, mid, vargs);
2925 break;
2926 default:
2927 LOG(FATAL) << "Unexpected invoke: " << invoke;
2928 }
2929 break;
2930 case Primitive::kPrimBoolean:
2931 result_check = "Z";
2932 switch (invoke) {
2933 case kVirtual:
2934 result.Z = baseEnv(env)->CallBooleanMethodV(env, obj, mid, vargs);
2935 break;
2936 case kDirect:
2937 result.Z = baseEnv(env)->CallNonvirtualBooleanMethodV(env, obj, c, mid, vargs);
2938 break;
2939 case kStatic:
2940 result.Z = baseEnv(env)->CallStaticBooleanMethodV(env, c, mid, vargs);
2941 break;
2942 default:
2943 LOG(FATAL) << "Unexpected invoke: " << invoke;
2944 }
2945 break;
2946 case Primitive::kPrimByte:
2947 result_check = "B";
2948 switch (invoke) {
2949 case kVirtual:
2950 result.B = baseEnv(env)->CallByteMethodV(env, obj, mid, vargs);
2951 break;
2952 case kDirect:
2953 result.B = baseEnv(env)->CallNonvirtualByteMethodV(env, obj, c, mid, vargs);
2954 break;
2955 case kStatic:
2956 result.B = baseEnv(env)->CallStaticByteMethodV(env, c, mid, vargs);
2957 break;
2958 default:
2959 LOG(FATAL) << "Unexpected invoke: " << invoke;
2960 }
2961 break;
2962 case Primitive::kPrimChar:
2963 result_check = "C";
2964 switch (invoke) {
2965 case kVirtual:
2966 result.C = baseEnv(env)->CallCharMethodV(env, obj, mid, vargs);
2967 break;
2968 case kDirect:
2969 result.C = baseEnv(env)->CallNonvirtualCharMethodV(env, obj, c, mid, vargs);
2970 break;
2971 case kStatic:
2972 result.C = baseEnv(env)->CallStaticCharMethodV(env, c, mid, vargs);
2973 break;
2974 default:
2975 LOG(FATAL) << "Unexpected invoke: " << invoke;
2976 }
2977 break;
2978 case Primitive::kPrimShort:
2979 result_check = "S";
2980 switch (invoke) {
2981 case kVirtual:
2982 result.S = baseEnv(env)->CallShortMethodV(env, obj, mid, vargs);
2983 break;
2984 case kDirect:
2985 result.S = baseEnv(env)->CallNonvirtualShortMethodV(env, obj, c, mid, vargs);
2986 break;
2987 case kStatic:
2988 result.S = baseEnv(env)->CallStaticShortMethodV(env, c, mid, vargs);
2989 break;
2990 default:
2991 LOG(FATAL) << "Unexpected invoke: " << invoke;
2992 }
2993 break;
2994 case Primitive::kPrimInt:
2995 result_check = "I";
2996 switch (invoke) {
2997 case kVirtual:
2998 result.I = baseEnv(env)->CallIntMethodV(env, obj, mid, vargs);
2999 break;
3000 case kDirect:
3001 result.I = baseEnv(env)->CallNonvirtualIntMethodV(env, obj, c, mid, vargs);
3002 break;
3003 case kStatic:
3004 result.I = baseEnv(env)->CallStaticIntMethodV(env, c, mid, vargs);
3005 break;
3006 default:
3007 LOG(FATAL) << "Unexpected invoke: " << invoke;
3008 }
3009 break;
3010 case Primitive::kPrimLong:
3011 result_check = "J";
3012 switch (invoke) {
3013 case kVirtual:
3014 result.J = baseEnv(env)->CallLongMethodV(env, obj, mid, vargs);
3015 break;
3016 case kDirect:
3017 result.J = baseEnv(env)->CallNonvirtualLongMethodV(env, obj, c, mid, vargs);
3018 break;
3019 case kStatic:
3020 result.J = baseEnv(env)->CallStaticLongMethodV(env, c, mid, vargs);
3021 break;
3022 default:
3023 LOG(FATAL) << "Unexpected invoke: " << invoke;
3024 }
3025 break;
3026 case Primitive::kPrimFloat:
3027 result_check = "F";
3028 switch (invoke) {
3029 case kVirtual:
3030 result.F = baseEnv(env)->CallFloatMethodV(env, obj, mid, vargs);
3031 break;
3032 case kDirect:
3033 result.F = baseEnv(env)->CallNonvirtualFloatMethodV(env, obj, c, mid, vargs);
3034 break;
3035 case kStatic:
3036 result.F = baseEnv(env)->CallStaticFloatMethodV(env, c, mid, vargs);
3037 break;
3038 default:
3039 LOG(FATAL) << "Unexpected invoke: " << invoke;
3040 }
3041 break;
3042 case Primitive::kPrimDouble:
3043 result_check = "D";
3044 switch (invoke) {
3045 case kVirtual:
3046 result.D = baseEnv(env)->CallDoubleMethodV(env, obj, mid, vargs);
3047 break;
3048 case kDirect:
3049 result.D = baseEnv(env)->CallNonvirtualDoubleMethodV(env, obj, c, mid, vargs);
3050 break;
3051 case kStatic:
3052 result.D = baseEnv(env)->CallStaticDoubleMethodV(env, c, mid, vargs);
3053 break;
3054 default:
3055 LOG(FATAL) << "Unexpected invoke: " << invoke;
3056 }
3057 break;
3058 case Primitive::kPrimVoid:
3059 result_check = "V";
3060 result.V = nullptr;
3061 switch (invoke) {
3062 case kVirtual:
3063 baseEnv(env)->CallVoidMethodV(env, obj, mid, vargs);
3064 break;
3065 case kDirect:
3066 baseEnv(env)->CallNonvirtualVoidMethodV(env, obj, c, mid, vargs);
3067 break;
3068 case kStatic:
3069 baseEnv(env)->CallStaticVoidMethodV(env, c, mid, vargs);
3070 break;
3071 default:
3072 LOG(FATAL) << "Unexpected invoke: " << invoke;
3073 }
3074 break;
3075 default:
3076 LOG(FATAL) << "Unexpected return type: " << type;
3077 result_check = nullptr;
3078 }
3079 if (sc.Check(soa, false, result_check, &result)) {
3080 return result;
3081 }
3082 }
3083 result.J = 0;
3084 return result;
3085 }
3086
3087 static const void* GetStringCharsInternal(const char* function_name, JNIEnv* env, jstring string,
3088 jboolean* is_copy, bool utf, bool critical) {
3089 ScopedObjectAccess soa(env);
3090 int flags = critical ? kFlag_CritGet : kFlag_CritOkay;
3091 ScopedCheck sc(flags, function_name);
3092 JniValueType args[3] = {{.E = env}, {.s = string}, {.p = is_copy}};
3093 if (sc.Check(soa, true, "Esp", args)) {
3094 JniValueType result;
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003095 void* ptr;
Ian Rogers68d8b422014-07-17 11:09:10 -07003096 if (utf) {
3097 CHECK(!critical);
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003098 ptr = const_cast<char*>(baseEnv(env)->GetStringUTFChars(env, string, is_copy));
3099 result.u = reinterpret_cast<char*>(ptr);
Ian Rogers68d8b422014-07-17 11:09:10 -07003100 } else {
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003101 ptr = const_cast<jchar*>(critical ? baseEnv(env)->GetStringCritical(env, string, is_copy) :
3102 baseEnv(env)->GetStringChars(env, string, is_copy));
3103 result.p = ptr;
Ian Rogers68d8b422014-07-17 11:09:10 -07003104 }
3105 // TODO: could we be smarter about not copying when local_is_copy?
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003106 if (ptr != nullptr && soa.ForceCopy()) {
Ian Rogers68d8b422014-07-17 11:09:10 -07003107 if (utf) {
3108 size_t length_in_bytes = strlen(result.u) + 1;
3109 result.u =
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003110 reinterpret_cast<const char*>(GuardedCopy::Create(ptr, length_in_bytes, false));
Ian Rogers68d8b422014-07-17 11:09:10 -07003111 } else {
3112 size_t length_in_bytes = baseEnv(env)->GetStringLength(env, string) * 2;
3113 result.p =
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003114 reinterpret_cast<const jchar*>(GuardedCopy::Create(ptr, length_in_bytes, false));
Ian Rogers68d8b422014-07-17 11:09:10 -07003115 }
3116 if (is_copy != nullptr) {
3117 *is_copy = JNI_TRUE;
3118 }
3119 }
3120 if (sc.Check(soa, false, utf ? "u" : "p", &result)) {
3121 return utf ? result.u : result.p;
3122 }
3123 }
3124 return nullptr;
3125 }
3126
3127 static void ReleaseStringCharsInternal(const char* function_name, JNIEnv* env, jstring string,
3128 const void* chars, bool utf, bool critical) {
3129 ScopedObjectAccess soa(env);
3130 int flags = kFlag_ExcepOkay | kFlag_Release;
3131 if (critical) {
3132 flags |= kFlag_CritRelease;
3133 }
3134 ScopedCheck sc(flags, function_name);
3135 sc.CheckNonNull(chars);
3136 bool force_copy_ok = !soa.ForceCopy() || GuardedCopy::Check(function_name, chars, false);
3137 if (force_copy_ok && soa.ForceCopy()) {
3138 chars = reinterpret_cast<const jchar*>(GuardedCopy::Destroy(const_cast<void*>(chars)));
3139 }
3140 if (force_copy_ok) {
3141 JniValueType args[3] = {{.E = env}, {.s = string}, {.p = chars}};
3142 if (sc.Check(soa, true, utf ? "Esu" : "Esp", args)) {
3143 if (utf) {
3144 CHECK(!critical);
3145 baseEnv(env)->ReleaseStringUTFChars(env, string, reinterpret_cast<const char*>(chars));
3146 } else {
3147 if (critical) {
3148 baseEnv(env)->ReleaseStringCritical(env, string, reinterpret_cast<const jchar*>(chars));
3149 } else {
3150 baseEnv(env)->ReleaseStringChars(env, string, reinterpret_cast<const jchar*>(chars));
3151 }
3152 }
3153 JniValueType result;
3154 sc.Check(soa, false, "V", &result);
3155 }
3156 }
3157 }
3158
3159 static jarray NewPrimitiveArray(const char* function_name, JNIEnv* env, jsize length,
3160 Primitive::Type type) {
3161 ScopedObjectAccess soa(env);
Ian Rogers6a3c1fc2014-10-31 00:33:20 -07003162 ScopedCheck sc(kFlag_Default, function_name);
Ian Rogers68d8b422014-07-17 11:09:10 -07003163 JniValueType args[2] = {{.E = env}, {.z = length}};
3164 if (sc.Check(soa, true, "Ez", args)) {
3165 JniValueType result;
3166 switch (type) {
3167 case Primitive::kPrimBoolean:
3168 result.a = baseEnv(env)->NewBooleanArray(env, length);
3169 break;
3170 case Primitive::kPrimByte:
3171 result.a = baseEnv(env)->NewByteArray(env, length);
3172 break;
3173 case Primitive::kPrimChar:
3174 result.a = baseEnv(env)->NewCharArray(env, length);
3175 break;
3176 case Primitive::kPrimShort:
3177 result.a = baseEnv(env)->NewShortArray(env, length);
3178 break;
3179 case Primitive::kPrimInt:
3180 result.a = baseEnv(env)->NewIntArray(env, length);
3181 break;
3182 case Primitive::kPrimLong:
3183 result.a = baseEnv(env)->NewLongArray(env, length);
3184 break;
3185 case Primitive::kPrimFloat:
3186 result.a = baseEnv(env)->NewFloatArray(env, length);
3187 break;
3188 case Primitive::kPrimDouble:
3189 result.a = baseEnv(env)->NewDoubleArray(env, length);
3190 break;
3191 default:
3192 LOG(FATAL) << "Unexpected primitive type: " << type;
3193 }
3194 if (sc.Check(soa, false, "a", &result)) {
3195 return result.a;
3196 }
3197 }
3198 return nullptr;
3199 }
3200
3201 static void* GetPrimitiveArrayElements(const char* function_name, Primitive::Type type,
3202 JNIEnv* env, jarray array, jboolean* is_copy) {
3203 ScopedObjectAccess soa(env);
3204 ScopedCheck sc(kFlag_Default, function_name);
3205 JniValueType args[3] = {{.E = env}, {.a = array}, {.p = is_copy}};
3206 if (sc.Check(soa, true, "Eap", args) && sc.CheckPrimitiveArrayType(soa, array, type)) {
3207 JniValueType result;
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003208 void* ptr = nullptr;
Ian Rogers68d8b422014-07-17 11:09:10 -07003209 switch (type) {
3210 case Primitive::kPrimBoolean:
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003211 ptr = baseEnv(env)->GetBooleanArrayElements(env, down_cast<jbooleanArray>(array),
3212 is_copy);
Ian Rogers68d8b422014-07-17 11:09:10 -07003213 break;
3214 case Primitive::kPrimByte:
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003215 ptr = baseEnv(env)->GetByteArrayElements(env, down_cast<jbyteArray>(array), is_copy);
Ian Rogers68d8b422014-07-17 11:09:10 -07003216 break;
3217 case Primitive::kPrimChar:
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003218 ptr = baseEnv(env)->GetCharArrayElements(env, down_cast<jcharArray>(array), is_copy);
Ian Rogers68d8b422014-07-17 11:09:10 -07003219 break;
3220 case Primitive::kPrimShort:
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003221 ptr = baseEnv(env)->GetShortArrayElements(env, down_cast<jshortArray>(array), is_copy);
Ian Rogers68d8b422014-07-17 11:09:10 -07003222 break;
3223 case Primitive::kPrimInt:
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003224 ptr = baseEnv(env)->GetIntArrayElements(env, down_cast<jintArray>(array), is_copy);
Ian Rogers68d8b422014-07-17 11:09:10 -07003225 break;
3226 case Primitive::kPrimLong:
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003227 ptr = baseEnv(env)->GetLongArrayElements(env, down_cast<jlongArray>(array), is_copy);
Ian Rogers68d8b422014-07-17 11:09:10 -07003228 break;
3229 case Primitive::kPrimFloat:
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003230 ptr = baseEnv(env)->GetFloatArrayElements(env, down_cast<jfloatArray>(array), is_copy);
Ian Rogers68d8b422014-07-17 11:09:10 -07003231 break;
3232 case Primitive::kPrimDouble:
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003233 ptr = baseEnv(env)->GetDoubleArrayElements(env, down_cast<jdoubleArray>(array), is_copy);
Ian Rogers68d8b422014-07-17 11:09:10 -07003234 break;
3235 default:
3236 LOG(FATAL) << "Unexpected primitive type: " << type;
3237 }
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003238 if (ptr != nullptr && soa.ForceCopy()) {
3239 ptr = GuardedCopy::CreateGuardedPACopy(env, array, is_copy, ptr);
Ian Rogers68d8b422014-07-17 11:09:10 -07003240 if (is_copy != nullptr) {
3241 *is_copy = JNI_TRUE;
3242 }
3243 }
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003244 result.p = ptr;
Ian Rogers68d8b422014-07-17 11:09:10 -07003245 if (sc.Check(soa, false, "p", &result)) {
3246 return const_cast<void*>(result.p);
3247 }
3248 }
3249 return nullptr;
3250 }
3251
3252 static void ReleasePrimitiveArrayElements(const char* function_name, Primitive::Type type,
3253 JNIEnv* env, jarray array, void* elems, jint mode) {
3254 ScopedObjectAccess soa(env);
3255 ScopedCheck sc(kFlag_ExcepOkay, function_name);
3256 if (sc.CheckNonNull(elems) && sc.CheckPrimitiveArrayType(soa, array, type)) {
3257 if (soa.ForceCopy()) {
3258 elems = GuardedCopy::ReleaseGuardedPACopy(function_name, env, array, elems, mode);
3259 }
3260 if (!soa.ForceCopy() || elems != nullptr) {
3261 JniValueType args[4] = {{.E = env}, {.a = array}, {.p = elems}, {.r = mode}};
3262 if (sc.Check(soa, true, "Eapr", args)) {
3263 switch (type) {
3264 case Primitive::kPrimBoolean:
3265 baseEnv(env)->ReleaseBooleanArrayElements(env, down_cast<jbooleanArray>(array),
3266 reinterpret_cast<jboolean*>(elems), mode);
3267 break;
3268 case Primitive::kPrimByte:
3269 baseEnv(env)->ReleaseByteArrayElements(env, down_cast<jbyteArray>(array),
3270 reinterpret_cast<jbyte*>(elems), mode);
3271 break;
3272 case Primitive::kPrimChar:
3273 baseEnv(env)->ReleaseCharArrayElements(env, down_cast<jcharArray>(array),
3274 reinterpret_cast<jchar*>(elems), mode);
3275 break;
3276 case Primitive::kPrimShort:
3277 baseEnv(env)->ReleaseShortArrayElements(env, down_cast<jshortArray>(array),
3278 reinterpret_cast<jshort*>(elems), mode);
3279 break;
3280 case Primitive::kPrimInt:
3281 baseEnv(env)->ReleaseIntArrayElements(env, down_cast<jintArray>(array),
3282 reinterpret_cast<jint*>(elems), mode);
3283 break;
3284 case Primitive::kPrimLong:
3285 baseEnv(env)->ReleaseLongArrayElements(env, down_cast<jlongArray>(array),
3286 reinterpret_cast<jlong*>(elems), mode);
3287 break;
3288 case Primitive::kPrimFloat:
3289 baseEnv(env)->ReleaseFloatArrayElements(env, down_cast<jfloatArray>(array),
3290 reinterpret_cast<jfloat*>(elems), mode);
3291 break;
3292 case Primitive::kPrimDouble:
3293 baseEnv(env)->ReleaseDoubleArrayElements(env, down_cast<jdoubleArray>(array),
3294 reinterpret_cast<jdouble*>(elems), mode);
3295 break;
3296 default:
3297 LOG(FATAL) << "Unexpected primitive type: " << type;
3298 }
3299 JniValueType result;
3300 result.V = nullptr;
3301 sc.Check(soa, false, "V", &result);
3302 }
3303 }
3304 }
3305 }
3306
3307 static void GetPrimitiveArrayRegion(const char* function_name, Primitive::Type type, JNIEnv* env,
3308 jarray array, jsize start, jsize len, void* buf) {
3309 ScopedObjectAccess soa(env);
3310 ScopedCheck sc(kFlag_Default, function_name);
3311 JniValueType args[5] = {{.E = env}, {.a = array}, {.z = start}, {.z = len}, {.p = buf}};
3312 // Note: the start and len arguments are checked as 'I' rather than 'z' as invalid indices
3313 // result in ArrayIndexOutOfBoundsExceptions in the base implementation.
3314 if (sc.Check(soa, true, "EaIIp", args) && sc.CheckPrimitiveArrayType(soa, array, type)) {
3315 switch (type) {
3316 case Primitive::kPrimBoolean:
3317 baseEnv(env)->GetBooleanArrayRegion(env, down_cast<jbooleanArray>(array), start, len,
3318 reinterpret_cast<jboolean*>(buf));
3319 break;
3320 case Primitive::kPrimByte:
3321 baseEnv(env)->GetByteArrayRegion(env, down_cast<jbyteArray>(array), start, len,
3322 reinterpret_cast<jbyte*>(buf));
3323 break;
3324 case Primitive::kPrimChar:
3325 baseEnv(env)->GetCharArrayRegion(env, down_cast<jcharArray>(array), start, len,
3326 reinterpret_cast<jchar*>(buf));
3327 break;
3328 case Primitive::kPrimShort:
3329 baseEnv(env)->GetShortArrayRegion(env, down_cast<jshortArray>(array), start, len,
3330 reinterpret_cast<jshort*>(buf));
3331 break;
3332 case Primitive::kPrimInt:
3333 baseEnv(env)->GetIntArrayRegion(env, down_cast<jintArray>(array), start, len,
3334 reinterpret_cast<jint*>(buf));
3335 break;
3336 case Primitive::kPrimLong:
3337 baseEnv(env)->GetLongArrayRegion(env, down_cast<jlongArray>(array), start, len,
3338 reinterpret_cast<jlong*>(buf));
3339 break;
3340 case Primitive::kPrimFloat:
3341 baseEnv(env)->GetFloatArrayRegion(env, down_cast<jfloatArray>(array), start, len,
3342 reinterpret_cast<jfloat*>(buf));
3343 break;
3344 case Primitive::kPrimDouble:
3345 baseEnv(env)->GetDoubleArrayRegion(env, down_cast<jdoubleArray>(array), start, len,
3346 reinterpret_cast<jdouble*>(buf));
3347 break;
3348 default:
3349 LOG(FATAL) << "Unexpected primitive type: " << type;
3350 }
3351 JniValueType result;
3352 result.V = nullptr;
3353 sc.Check(soa, false, "V", &result);
3354 }
3355 }
3356
3357 static void SetPrimitiveArrayRegion(const char* function_name, Primitive::Type type, JNIEnv* env,
3358 jarray array, jsize start, jsize len, const void* buf) {
3359 ScopedObjectAccess soa(env);
3360 ScopedCheck sc(kFlag_Default, function_name);
3361 JniValueType args[5] = {{.E = env}, {.a = array}, {.z = start}, {.z = len}, {.p = buf}};
3362 // Note: the start and len arguments are checked as 'I' rather than 'z' as invalid indices
3363 // result in ArrayIndexOutOfBoundsExceptions in the base implementation.
3364 if (sc.Check(soa, true, "EaIIp", args) && sc.CheckPrimitiveArrayType(soa, array, type)) {
3365 switch (type) {
3366 case Primitive::kPrimBoolean:
3367 baseEnv(env)->SetBooleanArrayRegion(env, down_cast<jbooleanArray>(array), start, len,
3368 reinterpret_cast<const jboolean*>(buf));
3369 break;
3370 case Primitive::kPrimByte:
3371 baseEnv(env)->SetByteArrayRegion(env, down_cast<jbyteArray>(array), start, len,
3372 reinterpret_cast<const jbyte*>(buf));
3373 break;
3374 case Primitive::kPrimChar:
3375 baseEnv(env)->SetCharArrayRegion(env, down_cast<jcharArray>(array), start, len,
3376 reinterpret_cast<const jchar*>(buf));
3377 break;
3378 case Primitive::kPrimShort:
3379 baseEnv(env)->SetShortArrayRegion(env, down_cast<jshortArray>(array), start, len,
3380 reinterpret_cast<const jshort*>(buf));
3381 break;
3382 case Primitive::kPrimInt:
3383 baseEnv(env)->SetIntArrayRegion(env, down_cast<jintArray>(array), start, len,
3384 reinterpret_cast<const jint*>(buf));
3385 break;
3386 case Primitive::kPrimLong:
3387 baseEnv(env)->SetLongArrayRegion(env, down_cast<jlongArray>(array), start, len,
3388 reinterpret_cast<const jlong*>(buf));
3389 break;
3390 case Primitive::kPrimFloat:
3391 baseEnv(env)->SetFloatArrayRegion(env, down_cast<jfloatArray>(array), start, len,
3392 reinterpret_cast<const jfloat*>(buf));
3393 break;
3394 case Primitive::kPrimDouble:
3395 baseEnv(env)->SetDoubleArrayRegion(env, down_cast<jdoubleArray>(array), start, len,
3396 reinterpret_cast<const jdouble*>(buf));
3397 break;
3398 default:
3399 LOG(FATAL) << "Unexpected primitive type: " << type;
3400 }
3401 JniValueType result;
3402 result.V = nullptr;
3403 sc.Check(soa, false, "V", &result);
3404 }
3405 }
Elliott Hughesa2501992011-08-26 19:39:54 -07003406};
3407
3408const JNINativeInterface gCheckNativeInterface = {
Ian Rogersef7d42f2014-01-06 12:55:46 -08003409 nullptr, // reserved0.
3410 nullptr, // reserved1.
3411 nullptr, // reserved2.
3412 nullptr, // reserved3.
Elliott Hughesa2501992011-08-26 19:39:54 -07003413 CheckJNI::GetVersion,
3414 CheckJNI::DefineClass,
3415 CheckJNI::FindClass,
3416 CheckJNI::FromReflectedMethod,
3417 CheckJNI::FromReflectedField,
3418 CheckJNI::ToReflectedMethod,
3419 CheckJNI::GetSuperclass,
3420 CheckJNI::IsAssignableFrom,
3421 CheckJNI::ToReflectedField,
3422 CheckJNI::Throw,
3423 CheckJNI::ThrowNew,
3424 CheckJNI::ExceptionOccurred,
3425 CheckJNI::ExceptionDescribe,
3426 CheckJNI::ExceptionClear,
3427 CheckJNI::FatalError,
3428 CheckJNI::PushLocalFrame,
3429 CheckJNI::PopLocalFrame,
3430 CheckJNI::NewGlobalRef,
3431 CheckJNI::DeleteGlobalRef,
3432 CheckJNI::DeleteLocalRef,
3433 CheckJNI::IsSameObject,
3434 CheckJNI::NewLocalRef,
3435 CheckJNI::EnsureLocalCapacity,
3436 CheckJNI::AllocObject,
3437 CheckJNI::NewObject,
3438 CheckJNI::NewObjectV,
3439 CheckJNI::NewObjectA,
3440 CheckJNI::GetObjectClass,
3441 CheckJNI::IsInstanceOf,
3442 CheckJNI::GetMethodID,
3443 CheckJNI::CallObjectMethod,
3444 CheckJNI::CallObjectMethodV,
3445 CheckJNI::CallObjectMethodA,
3446 CheckJNI::CallBooleanMethod,
3447 CheckJNI::CallBooleanMethodV,
3448 CheckJNI::CallBooleanMethodA,
3449 CheckJNI::CallByteMethod,
3450 CheckJNI::CallByteMethodV,
3451 CheckJNI::CallByteMethodA,
3452 CheckJNI::CallCharMethod,
3453 CheckJNI::CallCharMethodV,
3454 CheckJNI::CallCharMethodA,
3455 CheckJNI::CallShortMethod,
3456 CheckJNI::CallShortMethodV,
3457 CheckJNI::CallShortMethodA,
3458 CheckJNI::CallIntMethod,
3459 CheckJNI::CallIntMethodV,
3460 CheckJNI::CallIntMethodA,
3461 CheckJNI::CallLongMethod,
3462 CheckJNI::CallLongMethodV,
3463 CheckJNI::CallLongMethodA,
3464 CheckJNI::CallFloatMethod,
3465 CheckJNI::CallFloatMethodV,
3466 CheckJNI::CallFloatMethodA,
3467 CheckJNI::CallDoubleMethod,
3468 CheckJNI::CallDoubleMethodV,
3469 CheckJNI::CallDoubleMethodA,
3470 CheckJNI::CallVoidMethod,
3471 CheckJNI::CallVoidMethodV,
3472 CheckJNI::CallVoidMethodA,
3473 CheckJNI::CallNonvirtualObjectMethod,
3474 CheckJNI::CallNonvirtualObjectMethodV,
3475 CheckJNI::CallNonvirtualObjectMethodA,
3476 CheckJNI::CallNonvirtualBooleanMethod,
3477 CheckJNI::CallNonvirtualBooleanMethodV,
3478 CheckJNI::CallNonvirtualBooleanMethodA,
3479 CheckJNI::CallNonvirtualByteMethod,
3480 CheckJNI::CallNonvirtualByteMethodV,
3481 CheckJNI::CallNonvirtualByteMethodA,
3482 CheckJNI::CallNonvirtualCharMethod,
3483 CheckJNI::CallNonvirtualCharMethodV,
3484 CheckJNI::CallNonvirtualCharMethodA,
3485 CheckJNI::CallNonvirtualShortMethod,
3486 CheckJNI::CallNonvirtualShortMethodV,
3487 CheckJNI::CallNonvirtualShortMethodA,
3488 CheckJNI::CallNonvirtualIntMethod,
3489 CheckJNI::CallNonvirtualIntMethodV,
3490 CheckJNI::CallNonvirtualIntMethodA,
3491 CheckJNI::CallNonvirtualLongMethod,
3492 CheckJNI::CallNonvirtualLongMethodV,
3493 CheckJNI::CallNonvirtualLongMethodA,
3494 CheckJNI::CallNonvirtualFloatMethod,
3495 CheckJNI::CallNonvirtualFloatMethodV,
3496 CheckJNI::CallNonvirtualFloatMethodA,
3497 CheckJNI::CallNonvirtualDoubleMethod,
3498 CheckJNI::CallNonvirtualDoubleMethodV,
3499 CheckJNI::CallNonvirtualDoubleMethodA,
3500 CheckJNI::CallNonvirtualVoidMethod,
3501 CheckJNI::CallNonvirtualVoidMethodV,
3502 CheckJNI::CallNonvirtualVoidMethodA,
3503 CheckJNI::GetFieldID,
3504 CheckJNI::GetObjectField,
3505 CheckJNI::GetBooleanField,
3506 CheckJNI::GetByteField,
3507 CheckJNI::GetCharField,
3508 CheckJNI::GetShortField,
3509 CheckJNI::GetIntField,
3510 CheckJNI::GetLongField,
3511 CheckJNI::GetFloatField,
3512 CheckJNI::GetDoubleField,
3513 CheckJNI::SetObjectField,
3514 CheckJNI::SetBooleanField,
3515 CheckJNI::SetByteField,
3516 CheckJNI::SetCharField,
3517 CheckJNI::SetShortField,
3518 CheckJNI::SetIntField,
3519 CheckJNI::SetLongField,
3520 CheckJNI::SetFloatField,
3521 CheckJNI::SetDoubleField,
3522 CheckJNI::GetStaticMethodID,
3523 CheckJNI::CallStaticObjectMethod,
3524 CheckJNI::CallStaticObjectMethodV,
3525 CheckJNI::CallStaticObjectMethodA,
3526 CheckJNI::CallStaticBooleanMethod,
3527 CheckJNI::CallStaticBooleanMethodV,
3528 CheckJNI::CallStaticBooleanMethodA,
3529 CheckJNI::CallStaticByteMethod,
3530 CheckJNI::CallStaticByteMethodV,
3531 CheckJNI::CallStaticByteMethodA,
3532 CheckJNI::CallStaticCharMethod,
3533 CheckJNI::CallStaticCharMethodV,
3534 CheckJNI::CallStaticCharMethodA,
3535 CheckJNI::CallStaticShortMethod,
3536 CheckJNI::CallStaticShortMethodV,
3537 CheckJNI::CallStaticShortMethodA,
3538 CheckJNI::CallStaticIntMethod,
3539 CheckJNI::CallStaticIntMethodV,
3540 CheckJNI::CallStaticIntMethodA,
3541 CheckJNI::CallStaticLongMethod,
3542 CheckJNI::CallStaticLongMethodV,
3543 CheckJNI::CallStaticLongMethodA,
3544 CheckJNI::CallStaticFloatMethod,
3545 CheckJNI::CallStaticFloatMethodV,
3546 CheckJNI::CallStaticFloatMethodA,
3547 CheckJNI::CallStaticDoubleMethod,
3548 CheckJNI::CallStaticDoubleMethodV,
3549 CheckJNI::CallStaticDoubleMethodA,
3550 CheckJNI::CallStaticVoidMethod,
3551 CheckJNI::CallStaticVoidMethodV,
3552 CheckJNI::CallStaticVoidMethodA,
3553 CheckJNI::GetStaticFieldID,
3554 CheckJNI::GetStaticObjectField,
3555 CheckJNI::GetStaticBooleanField,
3556 CheckJNI::GetStaticByteField,
3557 CheckJNI::GetStaticCharField,
3558 CheckJNI::GetStaticShortField,
3559 CheckJNI::GetStaticIntField,
3560 CheckJNI::GetStaticLongField,
3561 CheckJNI::GetStaticFloatField,
3562 CheckJNI::GetStaticDoubleField,
3563 CheckJNI::SetStaticObjectField,
3564 CheckJNI::SetStaticBooleanField,
3565 CheckJNI::SetStaticByteField,
3566 CheckJNI::SetStaticCharField,
3567 CheckJNI::SetStaticShortField,
3568 CheckJNI::SetStaticIntField,
3569 CheckJNI::SetStaticLongField,
3570 CheckJNI::SetStaticFloatField,
3571 CheckJNI::SetStaticDoubleField,
3572 CheckJNI::NewString,
3573 CheckJNI::GetStringLength,
3574 CheckJNI::GetStringChars,
3575 CheckJNI::ReleaseStringChars,
3576 CheckJNI::NewStringUTF,
3577 CheckJNI::GetStringUTFLength,
3578 CheckJNI::GetStringUTFChars,
3579 CheckJNI::ReleaseStringUTFChars,
3580 CheckJNI::GetArrayLength,
3581 CheckJNI::NewObjectArray,
3582 CheckJNI::GetObjectArrayElement,
3583 CheckJNI::SetObjectArrayElement,
3584 CheckJNI::NewBooleanArray,
3585 CheckJNI::NewByteArray,
3586 CheckJNI::NewCharArray,
3587 CheckJNI::NewShortArray,
3588 CheckJNI::NewIntArray,
3589 CheckJNI::NewLongArray,
3590 CheckJNI::NewFloatArray,
3591 CheckJNI::NewDoubleArray,
3592 CheckJNI::GetBooleanArrayElements,
3593 CheckJNI::GetByteArrayElements,
3594 CheckJNI::GetCharArrayElements,
3595 CheckJNI::GetShortArrayElements,
3596 CheckJNI::GetIntArrayElements,
3597 CheckJNI::GetLongArrayElements,
3598 CheckJNI::GetFloatArrayElements,
3599 CheckJNI::GetDoubleArrayElements,
3600 CheckJNI::ReleaseBooleanArrayElements,
3601 CheckJNI::ReleaseByteArrayElements,
3602 CheckJNI::ReleaseCharArrayElements,
3603 CheckJNI::ReleaseShortArrayElements,
3604 CheckJNI::ReleaseIntArrayElements,
3605 CheckJNI::ReleaseLongArrayElements,
3606 CheckJNI::ReleaseFloatArrayElements,
3607 CheckJNI::ReleaseDoubleArrayElements,
3608 CheckJNI::GetBooleanArrayRegion,
3609 CheckJNI::GetByteArrayRegion,
3610 CheckJNI::GetCharArrayRegion,
3611 CheckJNI::GetShortArrayRegion,
3612 CheckJNI::GetIntArrayRegion,
3613 CheckJNI::GetLongArrayRegion,
3614 CheckJNI::GetFloatArrayRegion,
3615 CheckJNI::GetDoubleArrayRegion,
3616 CheckJNI::SetBooleanArrayRegion,
3617 CheckJNI::SetByteArrayRegion,
3618 CheckJNI::SetCharArrayRegion,
3619 CheckJNI::SetShortArrayRegion,
3620 CheckJNI::SetIntArrayRegion,
3621 CheckJNI::SetLongArrayRegion,
3622 CheckJNI::SetFloatArrayRegion,
3623 CheckJNI::SetDoubleArrayRegion,
3624 CheckJNI::RegisterNatives,
3625 CheckJNI::UnregisterNatives,
3626 CheckJNI::MonitorEnter,
3627 CheckJNI::MonitorExit,
3628 CheckJNI::GetJavaVM,
3629 CheckJNI::GetStringRegion,
3630 CheckJNI::GetStringUTFRegion,
3631 CheckJNI::GetPrimitiveArrayCritical,
3632 CheckJNI::ReleasePrimitiveArrayCritical,
3633 CheckJNI::GetStringCritical,
3634 CheckJNI::ReleaseStringCritical,
3635 CheckJNI::NewWeakGlobalRef,
3636 CheckJNI::DeleteWeakGlobalRef,
3637 CheckJNI::ExceptionCheck,
3638 CheckJNI::NewDirectByteBuffer,
3639 CheckJNI::GetDirectBufferAddress,
3640 CheckJNI::GetDirectBufferCapacity,
3641 CheckJNI::GetObjectRefType,
3642};
3643
3644const JNINativeInterface* GetCheckJniNativeInterface() {
3645 return &gCheckNativeInterface;
3646}
3647
3648class CheckJII {
Elliott Hughesba8eee12012-01-24 20:25:24 -08003649 public:
Elliott Hughesa2501992011-08-26 19:39:54 -07003650 static jint DestroyJavaVM(JavaVM* vm) {
Ian Rogers68d8b422014-07-17 11:09:10 -07003651 ScopedCheck sc(kFlag_Invocation, __FUNCTION__, false);
3652 JniValueType args[1] = {{.v = vm}};
3653 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), true, "v", args);
3654 JniValueType result;
3655 result.i = BaseVm(vm)->DestroyJavaVM(vm);
Andreas Gampedef194e2015-02-19 15:19:50 -08003656 // Use null to signal that the JavaVM isn't valid anymore. DestroyJavaVM deletes the runtime,
3657 // which will delete the JavaVMExt.
3658 sc.CheckNonHeap(nullptr, false, "i", &result);
Ian Rogers68d8b422014-07-17 11:09:10 -07003659 return result.i;
Elliott Hughesa2501992011-08-26 19:39:54 -07003660 }
3661
3662 static jint AttachCurrentThread(JavaVM* vm, JNIEnv** p_env, void* thr_args) {
Ian Rogers68d8b422014-07-17 11:09:10 -07003663 ScopedCheck sc(kFlag_Invocation, __FUNCTION__);
3664 JniValueType args[3] = {{.v = vm}, {.p = p_env}, {.p = thr_args}};
3665 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), true, "vpp", args);
3666 JniValueType result;
3667 result.i = BaseVm(vm)->AttachCurrentThread(vm, p_env, thr_args);
3668 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), false, "i", &result);
3669 return result.i;
Elliott Hughesa2501992011-08-26 19:39:54 -07003670 }
3671
3672 static jint AttachCurrentThreadAsDaemon(JavaVM* vm, JNIEnv** p_env, void* thr_args) {
Ian Rogers68d8b422014-07-17 11:09:10 -07003673 ScopedCheck sc(kFlag_Invocation, __FUNCTION__);
3674 JniValueType args[3] = {{.v = vm}, {.p = p_env}, {.p = thr_args}};
3675 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), true, "vpp", args);
3676 JniValueType result;
3677 result.i = BaseVm(vm)->AttachCurrentThreadAsDaemon(vm, p_env, thr_args);
3678 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), false, "i", &result);
3679 return result.i;
Elliott Hughesa2501992011-08-26 19:39:54 -07003680 }
3681
3682 static jint DetachCurrentThread(JavaVM* vm) {
Ian Rogers68d8b422014-07-17 11:09:10 -07003683 ScopedCheck sc(kFlag_Invocation, __FUNCTION__);
3684 JniValueType args[1] = {{.v = vm}};
3685 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), true, "v", args);
3686 JniValueType result;
3687 result.i = BaseVm(vm)->DetachCurrentThread(vm);
3688 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), false, "i", &result);
3689 return result.i;
Elliott Hughesa2501992011-08-26 19:39:54 -07003690 }
3691
Ian Rogers68d8b422014-07-17 11:09:10 -07003692 static jint GetEnv(JavaVM* vm, void** p_env, jint version) {
3693 ScopedCheck sc(kFlag_Invocation, __FUNCTION__);
3694 JniValueType args[3] = {{.v = vm}, {.p = p_env}, {.I = version}};
3695 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), true, "vpI", args);
3696 JniValueType result;
3697 result.i = BaseVm(vm)->GetEnv(vm, p_env, version);
3698 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), false, "i", &result);
3699 return result.i;
Elliott Hughesa2501992011-08-26 19:39:54 -07003700 }
3701
3702 private:
Ian Rogers68d8b422014-07-17 11:09:10 -07003703 static const JNIInvokeInterface* BaseVm(JavaVM* vm) {
3704 return reinterpret_cast<JavaVMExt*>(vm)->GetUncheckedFunctions();
Elliott Hughesa2501992011-08-26 19:39:54 -07003705 }
3706};
3707
3708const JNIInvokeInterface gCheckInvokeInterface = {
Ian Rogersef7d42f2014-01-06 12:55:46 -08003709 nullptr, // reserved0
3710 nullptr, // reserved1
3711 nullptr, // reserved2
Elliott Hughesa2501992011-08-26 19:39:54 -07003712 CheckJII::DestroyJavaVM,
3713 CheckJII::AttachCurrentThread,
3714 CheckJII::DetachCurrentThread,
3715 CheckJII::GetEnv,
3716 CheckJII::AttachCurrentThreadAsDaemon
3717};
3718
3719const JNIInvokeInterface* GetCheckJniInvokeInterface() {
3720 return &gCheckInvokeInterface;
3721}
3722
3723} // namespace art