blob: c5b06bb103a649cd5698fd721d223b14dd4b0370 [file] [log] [blame]
Ian Rogersdf20fe02011-07-20 20:34:16 -07001// Copyright 2011 Google Inc. All Rights Reserved.
2
Brian Carlstrom578bbdc2011-07-21 14:07:47 -07003#include "jni_internal.h"
Carl Shapiro2ed144c2011-07-26 16:52:08 -07004
Carl Shapiro9b9ba282011-08-14 15:30:39 -07005#include <cstdarg>
Elliott Hughes0af55432011-08-17 18:37:28 -07006#include <dlfcn.h>
Carl Shapiro9b9ba282011-08-14 15:30:39 -07007#include <sys/mman.h>
Elliott Hughes0af55432011-08-17 18:37:28 -07008#include <utility>
9#include <vector>
Carl Shapiro2ed144c2011-07-26 16:52:08 -070010
Elliott Hughes18c07532011-08-18 15:50:51 -070011#include "assembler.h"
Elliott Hughes40ef99e2011-08-11 17:44:34 -070012#include "class_linker.h"
Carl Shapiroea4dca82011-08-01 13:45:38 -070013#include "jni.h"
Brian Carlstrom578bbdc2011-07-21 14:07:47 -070014#include "logging.h"
Carl Shapiro9b9ba282011-08-14 15:30:39 -070015#include "object.h"
Carl Shapiro2ed144c2011-07-26 16:52:08 -070016#include "runtime.h"
Carl Shapirofc322c72011-07-27 00:20:01 -070017#include "scoped_ptr.h"
18#include "stringpiece.h"
Carl Shapiro2ed144c2011-07-26 16:52:08 -070019#include "thread.h"
Ian Rogersdf20fe02011-07-20 20:34:16 -070020
buzbeec143c552011-08-20 17:38:58 -070021extern bool oatCompileMethod(art::Method*, art::InstructionSet);
22
Ian Rogersdf20fe02011-07-20 20:34:16 -070023namespace art {
24
Elliott Hughescdf53122011-08-19 15:46:09 -070025// This is private API, but with two different implementations: ARM and x86.
26void CreateInvokeStub(Assembler* assembler, Method* method);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -070027
Elliott Hughescdf53122011-08-19 15:46:09 -070028// TODO: this should be in our anonymous namespace, but is currently needed
29// for testing in "jni_internal_test.cc".
30bool EnsureInvokeStub(Method* method) {
31 if (method->GetInvokeStub() != NULL) {
32 return true;
33 }
34 // TODO: use signature to find a matching stub
35 // TODO: failed, acquire a lock on the stub table
36 Assembler assembler;
37 CreateInvokeStub(&assembler, method);
38 // TODO: store native_entry in the stub table
39 int prot = PROT_READ | PROT_WRITE | PROT_EXEC;
40 size_t length = assembler.CodeSize();
41 void* addr = mmap(NULL, length, prot, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
42 if (addr == MAP_FAILED) {
Elliott Hughesa0b8feb2011-08-20 09:50:55 -070043 PLOG(FATAL) << "mmap failed for " << PrettyMethod(method, true);
Elliott Hughescdf53122011-08-19 15:46:09 -070044 }
45 MemoryRegion region(addr, length);
46 assembler.FinalizeInstructions(region);
47 method->SetInvokeStub(reinterpret_cast<Method::InvokeStub*>(region.pointer()));
48 return true;
49}
Elliott Hughes0af55432011-08-17 18:37:28 -070050
Elliott Hughescdf53122011-08-19 15:46:09 -070051// TODO: this can't be in our anonymous namespace because of the map in JavaVM.
52class SharedLibrary {
53public:
54 SharedLibrary(const std::string& path, void* handle, Object* class_loader)
55 : path_(path),
56 handle_(handle),
57 jni_on_load_lock_(Mutex::Create("JNI_OnLoad lock")),
58 jni_on_load_tid_(Thread::Current()->GetId()),
59 jni_on_load_result_(kPending) {
Elliott Hughes5174fe62011-08-23 15:12:35 -070060 pthread_cond_init(&jni_on_load_cond_, NULL);
Elliott Hughes18c07532011-08-18 15:50:51 -070061 }
62
63 ~SharedLibrary() {
Elliott Hughescdf53122011-08-19 15:46:09 -070064 delete jni_on_load_lock_;
Elliott Hughes0af55432011-08-17 18:37:28 -070065 }
66
Elliott Hughescdf53122011-08-19 15:46:09 -070067 Object* GetClassLoader() {
68 return class_loader_;
Elliott Hughes0af55432011-08-17 18:37:28 -070069 }
70
Elliott Hughescdf53122011-08-19 15:46:09 -070071 /*
72 * Check the result of an earlier call to JNI_OnLoad on this library. If
73 * the call has not yet finished in another thread, wait for it.
74 */
75 bool CheckOnLoadResult(JavaVMExt* vm) {
76 Thread* self = Thread::Current();
77 if (jni_on_load_tid_ == self->GetId()) {
78 // Check this so we don't end up waiting for ourselves. We need
79 // to return "true" so the caller can continue.
80 LOG(INFO) << *self << " recursive attempt to load library "
81 << "\"" << path_ << "\"";
82 return true;
Elliott Hughes0af55432011-08-17 18:37:28 -070083 }
84
Elliott Hughes5174fe62011-08-23 15:12:35 -070085 MutexLock mu(jni_on_load_lock_);
Elliott Hughescdf53122011-08-19 15:46:09 -070086 while (jni_on_load_result_ == kPending) {
87 if (vm->verbose_jni) {
88 LOG(INFO) << "[" << *self << " waiting for \"" << path_ << "\" "
89 << "JNI_OnLoad...]";
Elliott Hughes0af55432011-08-17 18:37:28 -070090 }
Elliott Hughescdf53122011-08-19 15:46:09 -070091 Thread::State old_state = self->GetState();
92 self->SetState(Thread::kWaiting); // TODO: VMWAIT
Elliott Hughes5174fe62011-08-23 15:12:35 -070093 pthread_cond_wait(&jni_on_load_cond_, &(jni_on_load_lock_->lock_impl_));
Elliott Hughes0af55432011-08-17 18:37:28 -070094 self->SetState(old_state);
Elliott Hughes0af55432011-08-17 18:37:28 -070095 }
96
Elliott Hughescdf53122011-08-19 15:46:09 -070097 bool okay = (jni_on_load_result_ == kOkay);
98 if (vm->verbose_jni) {
99 LOG(INFO) << "[Earlier JNI_OnLoad for \"" << path_ << "\" "
100 << (okay ? "succeeded" : "failed") << "]";
101 }
102 return okay;
103 }
104
105 void SetResult(bool result) {
106 jni_on_load_result_ = result ? kOkay : kFailed;
107 jni_on_load_tid_ = 0;
Elliott Hughes0af55432011-08-17 18:37:28 -0700108
109 // Broadcast a wakeup to anybody sleeping on the condition variable.
Elliott Hughes5174fe62011-08-23 15:12:35 -0700110 MutexLock mu(jni_on_load_lock_);
111 pthread_cond_broadcast(&jni_on_load_cond_);
Elliott Hughes0af55432011-08-17 18:37:28 -0700112 }
Elliott Hughescdf53122011-08-19 15:46:09 -0700113
114 private:
115 enum JNI_OnLoadState {
116 kPending,
117 kFailed,
118 kOkay,
119 };
120
121 // Path to library "/system/lib/libjni.so".
122 std::string path_;
123
124 // The void* returned by dlopen(3).
125 void* handle_;
126
127 // The ClassLoader this library is associated with.
128 Object* class_loader_;
129
130 // Guards remaining items.
131 Mutex* jni_on_load_lock_;
132 // Wait for JNI_OnLoad in other thread.
133 pthread_cond_t jni_on_load_cond_;
134 // Recursive invocation guard.
135 uint32_t jni_on_load_tid_;
136 // Result of earlier JNI_OnLoad call.
137 JNI_OnLoadState jni_on_load_result_;
138};
139
140namespace {
Elliott Hughes0af55432011-08-17 18:37:28 -0700141
Elliott Hughes22f40932011-08-12 13:06:37 -0700142// Entry/exit processing for all JNI calls.
143//
144// This performs the necessary thread state switching, lets us amortize the
145// cost of working out the current thread, and lets us check (and repair) apps
146// that are using a JNIEnv on the wrong thread.
147class ScopedJniThreadState {
148 public:
Elliott Hughesc5f7c912011-08-18 14:00:42 -0700149 explicit ScopedJniThreadState(JNIEnv* env)
150 : env_(reinterpret_cast<JNIEnvExt*>(env)) {
Elliott Hughesb20a5542011-08-12 18:03:12 -0700151 self_ = ThreadForEnv(env);
Elliott Hughes22f40932011-08-12 13:06:37 -0700152 self_->SetState(Thread::kRunnable);
153 }
154
155 ~ScopedJniThreadState() {
156 self_->SetState(Thread::kNative);
157 }
158
Elliott Hughesc5f7c912011-08-18 14:00:42 -0700159 JNIEnvExt* Env() {
160 return env_;
161 }
162
Elliott Hughesb20a5542011-08-12 18:03:12 -0700163 Thread* Self() {
Elliott Hughes22f40932011-08-12 13:06:37 -0700164 return self_;
165 }
166
Elliott Hughesb20a5542011-08-12 18:03:12 -0700167 private:
168 static Thread* ThreadForEnv(JNIEnv* env) {
Elliott Hughes22f40932011-08-12 13:06:37 -0700169 // TODO: need replacement for gDvmJni.
170 bool workAroundAppJniBugs = true;
171 Thread* env_self = reinterpret_cast<JNIEnvExt*>(env)->self;
172 Thread* self = workAroundAppJniBugs ? Thread::Current() : env_self;
173 if (self != env_self) {
Elliott Hughes330304d2011-08-12 14:28:05 -0700174 LOG(ERROR) << "JNI ERROR: JNIEnv for " << *env_self
175 << " used on " << *self;
176 // TODO: dump stack
Elliott Hughes22f40932011-08-12 13:06:37 -0700177 }
178 return self;
179 }
180
Elliott Hughesc5f7c912011-08-18 14:00:42 -0700181 JNIEnvExt* env_;
Elliott Hughes22f40932011-08-12 13:06:37 -0700182 Thread* self_;
183 DISALLOW_COPY_AND_ASSIGN(ScopedJniThreadState);
184};
185
Elliott Hughesc5f7c912011-08-18 14:00:42 -0700186/*
187 * Add a local reference for an object to the current stack frame. When
188 * the native function returns, the reference will be discarded.
189 *
190 * We need to allow the same reference to be added multiple times.
191 *
192 * This will be called on otherwise unreferenced objects. We cannot do
193 * GC allocations here, and it's best if we don't grab a mutex.
194 *
195 * Returns the local reference (currently just the same pointer that was
196 * passed in), or NULL on failure.
197 */
Elliott Hughes8a26c5c2011-08-15 18:35:43 -0700198template<typename T>
199T AddLocalReference(ScopedJniThreadState& ts, Object* obj) {
Elliott Hughesc5f7c912011-08-18 14:00:42 -0700200 if (obj == NULL) {
201 return NULL;
202 }
203
204 IndirectReferenceTable& locals = ts.Env()->locals;
205
206 uint32_t cookie = IRT_FIRST_SEGMENT; // TODO
207 IndirectRef ref = locals.Add(cookie, obj);
208 if (ref == NULL) {
209 // TODO: just change Add's DCHECK to CHECK and lose this?
210 locals.Dump();
211 LOG(FATAL) << "Failed adding to JNI local reference table "
212 << "(has " << locals.Capacity() << " entries)";
213 // TODO: dvmDumpThread(dvmThreadSelf(), false);
214 }
215
216#if 0 // TODO: fix this to understand PushLocalFrame, so we can turn it on.
217 if (ts.Env()->check_jni) {
218 size_t entry_count = locals.Capacity();
219 if (entry_count > 16) {
Elliott Hughese5b0dc82011-08-23 09:59:02 -0700220 std::string class_descriptor(PrettyDescriptor(obj->GetClass()->GetDescriptor()));
Elliott Hughesc5f7c912011-08-18 14:00:42 -0700221 LOG(WARNING) << "Warning: more than 16 JNI local references: "
Elliott Hughese5b0dc82011-08-23 09:59:02 -0700222 << entry_count << " (most recent was a " << class_descriptor << ")";
Elliott Hughesc5f7c912011-08-18 14:00:42 -0700223 locals.Dump();
224 // TODO: dvmDumpThread(dvmThreadSelf(), false);
225 // dvmAbort();
226 }
227 }
228#endif
229
230 if (false /*gDvmJni.workAroundAppJniBugs*/) { // TODO
231 // Hand out direct pointers to support broken old apps.
232 return reinterpret_cast<T>(obj);
233 }
234
235 return reinterpret_cast<T>(ref);
236}
237
Elliott Hughescdf53122011-08-19 15:46:09 -0700238jweak AddWeakGlobalReference(ScopedJniThreadState& ts, Object* obj) {
239 if (obj == NULL) {
240 return NULL;
241 }
242 JavaVMExt* vm = Runtime::Current()->GetJavaVM();
243 IndirectReferenceTable& weak_globals = vm->weak_globals;
244 MutexLock mu(vm->weak_globals_lock);
245 IndirectRef ref = weak_globals.Add(IRT_FIRST_SEGMENT, obj);
246 return reinterpret_cast<jweak>(ref);
247}
248
Elliott Hughesc5f7c912011-08-18 14:00:42 -0700249template<typename T>
250T Decode(ScopedJniThreadState& ts, jobject obj) {
251 if (obj == NULL) {
252 return NULL;
253 }
254
255 IndirectRef ref = reinterpret_cast<IndirectRef>(obj);
256 IndirectRefKind kind = GetIndirectRefKind(ref);
257 Object* result;
258 switch (kind) {
259 case kLocal:
260 {
261 IndirectReferenceTable& locals = ts.Env()->locals;
262 result = locals.Get(ref);
263 break;
264 }
265 case kGlobal:
266 {
267 JavaVMExt* vm = Runtime::Current()->GetJavaVM();
268 IndirectReferenceTable& globals = vm->globals;
Elliott Hughes18c07532011-08-18 15:50:51 -0700269 MutexLock mu(vm->globals_lock);
Elliott Hughesc5f7c912011-08-18 14:00:42 -0700270 result = globals.Get(ref);
271 break;
272 }
273 case kWeakGlobal:
274 {
275 JavaVMExt* vm = Runtime::Current()->GetJavaVM();
276 IndirectReferenceTable& weak_globals = vm->weak_globals;
Elliott Hughes18c07532011-08-18 15:50:51 -0700277 MutexLock mu(vm->weak_globals_lock);
Elliott Hughesc5f7c912011-08-18 14:00:42 -0700278 result = weak_globals.Get(ref);
279 if (result == kClearedJniWeakGlobal) {
280 // This is a special case where it's okay to return NULL.
281 return NULL;
282 }
283 break;
284 }
285 case kInvalid:
286 default:
Ian Rogersa8cd9f42011-08-19 16:43:41 -0700287 // TODO: make stack handle blocks more efficient
288 // Check if this is a local reference in a stack handle block
289 if (ts.Self()->ShbContains(obj)) {
290 return *reinterpret_cast<T*>(obj); // Read from stack handle block
291 }
Elliott Hughesc5f7c912011-08-18 14:00:42 -0700292 if (false /*gDvmJni.workAroundAppJniBugs*/) { // TODO
293 // Assume an invalid local reference is actually a direct pointer.
294 return reinterpret_cast<T>(obj);
295 }
296 LOG(FATAL) << "Invalid indirect reference " << obj;
297 return reinterpret_cast<T>(kInvalidIndirectRefObject);
298 }
299
300 if (result == NULL) {
301 LOG(FATAL) << "JNI ERROR (app bug): use of deleted " << kind << ": "
302 << obj;
303 }
304 return reinterpret_cast<T>(result);
Elliott Hughes8a26c5c2011-08-15 18:35:43 -0700305}
306
Elliott Hughescdf53122011-08-19 15:46:09 -0700307Field* DecodeField(ScopedJniThreadState& ts, jfieldID fid) {
308 return Decode<Field*>(ts, reinterpret_cast<jweak>(fid));
309}
Carl Shapiro9b9ba282011-08-14 15:30:39 -0700310
Elliott Hughescdf53122011-08-19 15:46:09 -0700311Method* DecodeMethod(ScopedJniThreadState& ts, jmethodID mid) {
312 return Decode<Method*>(ts, reinterpret_cast<jweak>(mid));
Carl Shapiro9b9ba282011-08-14 15:30:39 -0700313}
314
Elliott Hughesc5f7c912011-08-18 14:00:42 -0700315byte* CreateArgArray(ScopedJniThreadState& ts, Method* method, va_list ap) {
Carl Shapiro9b9ba282011-08-14 15:30:39 -0700316 size_t num_bytes = method->NumArgArrayBytes();
317 scoped_array<byte> arg_array(new byte[num_bytes]);
318 const StringPiece& shorty = method->GetShorty();
Ian Rogers4dd71f12011-08-16 14:16:02 -0700319 for (int i = 1, offset = 0; i < shorty.size(); ++i) {
Carl Shapiro9b9ba282011-08-14 15:30:39 -0700320 switch (shorty[i]) {
321 case 'Z':
322 case 'B':
323 case 'C':
324 case 'S':
325 case 'I':
326 *reinterpret_cast<int32_t*>(&arg_array[offset]) = va_arg(ap, jint);
327 offset += 4;
328 break;
329 case 'F':
330 *reinterpret_cast<float*>(&arg_array[offset]) = va_arg(ap, jdouble);
331 offset += 4;
332 break;
333 case 'L': {
Elliott Hughesc5f7c912011-08-18 14:00:42 -0700334 Object* obj = Decode<Object*>(ts, va_arg(ap, jobject));
Carl Shapiro9b9ba282011-08-14 15:30:39 -0700335 *reinterpret_cast<Object**>(&arg_array[offset]) = obj;
336 offset += sizeof(Object*);
337 break;
338 }
339 case 'D':
340 *reinterpret_cast<double*>(&arg_array[offset]) = va_arg(ap, jdouble);
341 offset += 8;
342 break;
343 case 'J':
344 *reinterpret_cast<int64_t*>(&arg_array[offset]) = va_arg(ap, jlong);
345 offset += 8;
346 break;
347 }
348 }
349 return arg_array.release();
350}
351
Elliott Hughesc5f7c912011-08-18 14:00:42 -0700352byte* CreateArgArray(ScopedJniThreadState& ts, Method* method, jvalue* args) {
Carl Shapiro9b9ba282011-08-14 15:30:39 -0700353 size_t num_bytes = method->NumArgArrayBytes();
354 scoped_array<byte> arg_array(new byte[num_bytes]);
355 const StringPiece& shorty = method->GetShorty();
Ian Rogers4dd71f12011-08-16 14:16:02 -0700356 for (int i = 1, offset = 0; i < shorty.size(); ++i) {
Carl Shapiro9b9ba282011-08-14 15:30:39 -0700357 switch (shorty[i]) {
358 case 'Z':
359 case 'B':
360 case 'C':
361 case 'S':
362 case 'I':
363 *reinterpret_cast<uint32_t*>(&arg_array[offset]) = args[i - 1].i;
364 offset += 4;
365 break;
366 case 'F':
367 *reinterpret_cast<float*>(&arg_array[offset]) = args[i - 1].f;
368 offset += 4;
369 break;
370 case 'L': {
Elliott Hughesc5f7c912011-08-18 14:00:42 -0700371 Object* obj = Decode<Object*>(ts, args[i - 1].l);
Carl Shapiro9b9ba282011-08-14 15:30:39 -0700372 *reinterpret_cast<Object**>(&arg_array[offset]) = obj;
373 offset += sizeof(Object*);
374 break;
375 }
376 case 'D':
377 *reinterpret_cast<double*>(&arg_array[offset]) = args[i - 1].d;
378 offset += 8;
379 break;
380 case 'J':
381 *reinterpret_cast<uint64_t*>(&arg_array[offset]) = args[i - 1].j;
382 offset += 8;
383 break;
384 }
385 }
386 return arg_array.release();
387}
388
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700389JValue InvokeWithArgArray(ScopedJniThreadState& ts, jobject obj,
Elliott Hughescdf53122011-08-19 15:46:09 -0700390 jmethodID mid, byte* args) {
391 Method* method = DecodeMethod(ts, mid);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700392 Object* rcvr = Decode<Object*>(ts, obj);
Ian Rogers6de08602011-08-19 14:52:39 -0700393 Thread* self = ts.Self();
394
395 // Push a transition back into managed code onto the linked list in thread
396 CHECK_EQ(Thread::kRunnable, self->GetState());
397 NativeToManagedRecord record;
398 self->PushNativeToManagedRecord(&record);
399
Carl Shapiro9b9ba282011-08-14 15:30:39 -0700400 // Call the invoke stub associated with the method
401 // Pass everything as arguments
402 const Method::InvokeStub* stub = method->GetInvokeStub();
403 CHECK(stub != NULL);
buzbeec143c552011-08-20 17:38:58 -0700404
405#ifdef __arm__
406 // Compile...
407 // TODO: not here!
408 oatCompileMethod(method, kThumb2);
409#endif
410
Carl Shapiro9b9ba282011-08-14 15:30:39 -0700411 JValue result;
buzbeec143c552011-08-20 17:38:58 -0700412 if (method->HasCode()) {
Ian Rogers6de08602011-08-19 14:52:39 -0700413 (*stub)(method, rcvr, self, args, &result);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700414 } else {
Elliott Hughesa0b8feb2011-08-20 09:50:55 -0700415 LOG(WARNING) << "Not invoking method with no associated code: "
416 << PrettyMethod(method, true);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700417 result.j = 0;
418 }
buzbeec143c552011-08-20 17:38:58 -0700419
Ian Rogers6de08602011-08-19 14:52:39 -0700420 // Pop transition
421 self->PopNativeToManagedRecord(record);
Carl Shapiro9b9ba282011-08-14 15:30:39 -0700422 return result;
423}
424
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700425JValue InvokeWithJValues(ScopedJniThreadState& ts, jobject obj,
Elliott Hughescdf53122011-08-19 15:46:09 -0700426 jmethodID mid, jvalue* args) {
427 Method* method = DecodeMethod(ts, mid);
Elliott Hughesc5f7c912011-08-18 14:00:42 -0700428 scoped_array<byte> arg_array(CreateArgArray(ts, method, args));
Elliott Hughescdf53122011-08-19 15:46:09 -0700429 return InvokeWithArgArray(ts, obj, mid, arg_array.get());
Carl Shapiro9b9ba282011-08-14 15:30:39 -0700430}
431
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700432JValue InvokeWithVarArgs(ScopedJniThreadState& ts, jobject obj,
Elliott Hughescdf53122011-08-19 15:46:09 -0700433 jmethodID mid, va_list args) {
434 Method* method = DecodeMethod(ts, mid);
Elliott Hughesc5f7c912011-08-18 14:00:42 -0700435 scoped_array<byte> arg_array(CreateArgArray(ts, method, args));
Elliott Hughescdf53122011-08-19 15:46:09 -0700436 return InvokeWithArgArray(ts, obj, mid, arg_array.get());
Carl Shapiroea4dca82011-08-01 13:45:38 -0700437}
438
Elliott Hughes6b436852011-08-12 10:16:44 -0700439// Section 12.3.2 of the JNI spec describes JNI class descriptors. They're
440// separated with slashes but aren't wrapped with "L;" like regular descriptors
441// (i.e. "a/b/C" rather than "La/b/C;"). Arrays of reference types are an
442// exception; there the "L;" must be present ("[La/b/C;"). Historically we've
443// supported names with dots too (such as "a.b.C").
444std::string NormalizeJniClassDescriptor(const char* name) {
445 std::string result;
446 // Add the missing "L;" if necessary.
447 if (name[0] == '[') {
448 result = name;
449 } else {
450 result += 'L';
451 result += name;
452 result += ';';
453 }
454 // Rewrite '.' as '/' for backwards compatibility.
Elliott Hughesa5b897e2011-08-16 11:33:06 -0700455 if (result.find('.') != std::string::npos) {
456 LOG(WARNING) << "Call to JNI FindClass with dots in name: "
457 << "\"" << name << "\"";
458 std::replace(result.begin(), result.end(), '.', '/');
Elliott Hughes6b436852011-08-12 10:16:44 -0700459 }
460 return result;
461}
462
Elliott Hughescdf53122011-08-19 15:46:09 -0700463jmethodID FindMethodID(ScopedJniThreadState& ts, jclass jni_class, const char* name, const char* sig, bool is_static) {
464 Class* c = Decode<Class*>(ts, jni_class);
Elliott Hughesf4c21c92011-08-19 17:31:31 -0700465 if (!Runtime::Current()->GetClassLinker()->EnsureInitialized(c)) {
466 return NULL;
Carl Shapiro83ab4f32011-08-15 20:21:39 -0700467 }
Elliott Hughescdf53122011-08-19 15:46:09 -0700468
469 Method* method = NULL;
470 if (is_static) {
471 method = c->FindDirectMethod(name, sig);
Ian Rogers4dd71f12011-08-16 14:16:02 -0700472 } else {
Elliott Hughescdf53122011-08-19 15:46:09 -0700473 method = c->FindVirtualMethod(name, sig);
474 if (method == NULL) {
475 // No virtual method matching the signature. Search declared
476 // private methods and constructors.
477 method = c->FindDeclaredDirectMethod(name, sig);
Ian Rogers4dd71f12011-08-16 14:16:02 -0700478 }
Carl Shapiro83ab4f32011-08-15 20:21:39 -0700479 }
Carl Shapiroea4dca82011-08-01 13:45:38 -0700480
Elliott Hughescdf53122011-08-19 15:46:09 -0700481 if (method == NULL || method->IsStatic() != is_static) {
482 Thread* self = Thread::Current();
Elliott Hughesa0b8feb2011-08-20 09:50:55 -0700483 std::string method_name(PrettyMethod(method, true));
Elliott Hughescdf53122011-08-19 15:46:09 -0700484 // TODO: try searching for the opposite kind of method from is_static
485 // for better diagnostics?
486 self->ThrowNewException("Ljava/lang/NoSuchMethodError;",
Elliott Hughesa0b8feb2011-08-20 09:50:55 -0700487 "no %s method %s", is_static ? "static" : "non-static",
488 method_name.c_str());
Elliott Hughescdf53122011-08-19 15:46:09 -0700489 return NULL;
490 }
Carl Shapiroea4dca82011-08-01 13:45:38 -0700491
Elliott Hughescdf53122011-08-19 15:46:09 -0700492 bool success = EnsureInvokeStub(method);
493 if (!success) {
494 // TODO: throw OutOfMemoryException
495 return NULL;
496 }
Carl Shapiroea4dca82011-08-01 13:45:38 -0700497
Elliott Hughescdf53122011-08-19 15:46:09 -0700498 return reinterpret_cast<jmethodID>(AddWeakGlobalReference(ts, method));
Carl Shapiroea4dca82011-08-01 13:45:38 -0700499}
500
Elliott Hughescdf53122011-08-19 15:46:09 -0700501jfieldID FindFieldID(ScopedJniThreadState& ts, jclass jni_class, const char* name, const char* sig, bool is_static) {
502 Class* c = Decode<Class*>(ts, jni_class);
Elliott Hughesf4c21c92011-08-19 17:31:31 -0700503 if (!Runtime::Current()->GetClassLinker()->EnsureInitialized(c)) {
504 return NULL;
Carl Shapiro83ab4f32011-08-15 20:21:39 -0700505 }
Elliott Hughescdf53122011-08-19 15:46:09 -0700506
507 Field* field = NULL;
508 if (is_static) {
509 field = c->FindStaticField(name, sig);
Ian Rogers4dd71f12011-08-16 14:16:02 -0700510 } else {
Elliott Hughescdf53122011-08-19 15:46:09 -0700511 field = c->FindInstanceField(name, sig);
Carl Shapiro9b9ba282011-08-14 15:30:39 -0700512 }
Carl Shapiroea4dca82011-08-01 13:45:38 -0700513
Elliott Hughescdf53122011-08-19 15:46:09 -0700514 if (field == NULL) {
515 Thread* self = Thread::Current();
Elliott Hughese5b0dc82011-08-23 09:59:02 -0700516 std::string class_descriptor(c->GetDescriptor()->ToModifiedUtf8());
Elliott Hughescdf53122011-08-19 15:46:09 -0700517 self->ThrowNewException("Ljava/lang/NoSuchFieldError;",
518 "no \"%s\" field \"%s\" in class \"%s\" or its superclasses", sig,
Elliott Hughese5b0dc82011-08-23 09:59:02 -0700519 name, class_descriptor.c_str());
Elliott Hughes8a26c5c2011-08-15 18:35:43 -0700520 return NULL;
521 }
Carl Shapiroea4dca82011-08-01 13:45:38 -0700522
Elliott Hughescdf53122011-08-19 15:46:09 -0700523 jweak fid = AddWeakGlobalReference(ts, field);
524 return reinterpret_cast<jfieldID>(fid);
Carl Shapiroea4dca82011-08-01 13:45:38 -0700525}
526
Elliott Hughesd8ddfd52011-08-15 14:32:53 -0700527template<typename JniT, typename ArtT>
528JniT NewPrimitiveArray(ScopedJniThreadState& ts, jsize length) {
529 CHECK_GE(length, 0); // TODO: ReportJniError
530 ArtT* result = ArtT::Alloc(length);
Elliott Hughes8a26c5c2011-08-15 18:35:43 -0700531 return AddLocalReference<JniT>(ts, result);
Elliott Hughesd8ddfd52011-08-15 14:32:53 -0700532}
533
Elliott Hughes814e4032011-08-23 12:07:56 -0700534void ThrowAIOOBE(ScopedJniThreadState& ts, Array* array, jsize start, jsize length, const char* identifier) {
535 std::string type(PrettyType(array));
536 ts.Self()->ThrowNewException("Ljava/lang/ArrayIndexOutOfBoundsException;",
537 "%s offset=%d length=%d %s.length=%d",
538 type.c_str(), start, length, identifier, array->GetLength());
539}
540
541template <typename JavaArrayT, typename JavaT, typename ArrayT>
542static void GetPrimitiveArrayRegion(ScopedJniThreadState& ts, JavaArrayT java_array, jsize start, jsize length, JavaT* buf) {
543 ArrayT* array = Decode<ArrayT*>(ts, java_array);
544 if (start < 0 || length < 0 || start + length > array->GetLength()) {
545 ThrowAIOOBE(ts, array, start, length, "src");
546 } else {
547 JavaT* data = array->GetData();
548 memcpy(buf, data + start, length * sizeof(JavaT));
549 }
550}
551
552template <typename JavaArrayT, typename JavaT, typename ArrayT>
553static void SetPrimitiveArrayRegion(ScopedJniThreadState& ts, JavaArrayT java_array, jsize start, jsize length, const JavaT* buf) {
554 ArrayT* array = Decode<ArrayT*>(ts, java_array);
555 if (start < 0 || length < 0 || start + length > array->GetLength()) {
556 ThrowAIOOBE(ts, array, start, length, "dst");
557 } else {
558 JavaT* data = array->GetData();
559 memcpy(data + start, buf, length * sizeof(JavaT));
560 }
561}
562
Elliott Hughescdf53122011-08-19 15:46:09 -0700563} // namespace
Carl Shapiroea4dca82011-08-01 13:45:38 -0700564
Elliott Hughescdf53122011-08-19 15:46:09 -0700565class JNI {
566 public:
Carl Shapiroea4dca82011-08-01 13:45:38 -0700567
Elliott Hughescdf53122011-08-19 15:46:09 -0700568 static jint GetVersion(JNIEnv* env) {
569 ScopedJniThreadState ts(env);
570 return JNI_VERSION_1_6;
571 }
Carl Shapiroea4dca82011-08-01 13:45:38 -0700572
Elliott Hughescdf53122011-08-19 15:46:09 -0700573 static jclass DefineClass(JNIEnv* env, const char*, jobject, const jbyte*, jsize) {
574 ScopedJniThreadState ts(env);
575 LOG(WARNING) << "JNI DefineClass is not supported";
Elliott Hughesf2682d52011-08-15 16:37:04 -0700576 return NULL;
577 }
578
Elliott Hughescdf53122011-08-19 15:46:09 -0700579 static jclass FindClass(JNIEnv* env, const char* name) {
580 ScopedJniThreadState ts(env);
581 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
582 std::string descriptor(NormalizeJniClassDescriptor(name));
583 // TODO: need to get the appropriate ClassLoader.
Elliott Hughesedcc09c2011-08-21 18:47:05 -0700584 ClassLoader* cl = ts.Self()->GetClassLoaderOverride();
buzbeec143c552011-08-20 17:38:58 -0700585 Class* c = class_linker->FindClass(descriptor, cl);
Elliott Hughescdf53122011-08-19 15:46:09 -0700586 return AddLocalReference<jclass>(ts, c);
Ian Rogers4dd71f12011-08-16 14:16:02 -0700587 }
Carl Shapiroea4dca82011-08-01 13:45:38 -0700588
Elliott Hughescdf53122011-08-19 15:46:09 -0700589 static jmethodID FromReflectedMethod(JNIEnv* env, jobject java_method) {
590 ScopedJniThreadState ts(env);
591 Method* method = Decode<Method*>(ts, java_method);
592 return reinterpret_cast<jmethodID>(AddWeakGlobalReference(ts, method));
Elliott Hughesf2682d52011-08-15 16:37:04 -0700593 }
Carl Shapiroea4dca82011-08-01 13:45:38 -0700594
Elliott Hughescdf53122011-08-19 15:46:09 -0700595 static jfieldID FromReflectedField(JNIEnv* env, jobject java_field) {
596 ScopedJniThreadState ts(env);
597 Field* field = Decode<Field*>(ts, java_field);
598 return reinterpret_cast<jfieldID>(AddWeakGlobalReference(ts, field));
599 }
Carl Shapiroea4dca82011-08-01 13:45:38 -0700600
Elliott Hughescdf53122011-08-19 15:46:09 -0700601 static jobject ToReflectedMethod(JNIEnv* env, jclass, jmethodID mid, jboolean) {
602 ScopedJniThreadState ts(env);
603 Method* method = DecodeMethod(ts, mid);
604 return AddLocalReference<jobject>(ts, method);
605 }
Carl Shapiroea4dca82011-08-01 13:45:38 -0700606
Elliott Hughescdf53122011-08-19 15:46:09 -0700607 static jobject ToReflectedField(JNIEnv* env, jclass, jfieldID fid, jboolean) {
608 ScopedJniThreadState ts(env);
609 Field* field = DecodeField(ts, fid);
610 return AddLocalReference<jobject>(ts, field);
611 }
Carl Shapiroea4dca82011-08-01 13:45:38 -0700612
Elliott Hughes37f7a402011-08-22 18:56:01 -0700613 static jclass GetObjectClass(JNIEnv* env, jobject java_object) {
614 ScopedJniThreadState ts(env);
615 Object* o = Decode<Object*>(ts, java_object);
616 return AddLocalReference<jclass>(ts, o->GetClass());
617 }
618
Elliott Hughes885c3bd2011-08-22 16:59:20 -0700619 static jclass GetSuperclass(JNIEnv* env, jclass java_class) {
Elliott Hughescdf53122011-08-19 15:46:09 -0700620 ScopedJniThreadState ts(env);
Elliott Hughes885c3bd2011-08-22 16:59:20 -0700621 Class* c = Decode<Class*>(ts, java_class);
622 return AddLocalReference<jclass>(ts, c->GetSuperClass());
Elliott Hughescdf53122011-08-19 15:46:09 -0700623 }
Carl Shapiroea4dca82011-08-01 13:45:38 -0700624
Elliott Hughes37f7a402011-08-22 18:56:01 -0700625 static jboolean IsAssignableFrom(JNIEnv* env, jclass java_class1, jclass java_class2) {
Elliott Hughescdf53122011-08-19 15:46:09 -0700626 ScopedJniThreadState ts(env);
Elliott Hughes37f7a402011-08-22 18:56:01 -0700627 Class* c1 = Decode<Class*>(ts, java_class1);
628 Class* c2 = Decode<Class*>(ts, java_class2);
629 return c1->IsAssignableFrom(c2) ? JNI_TRUE : JNI_FALSE;
Elliott Hughescdf53122011-08-19 15:46:09 -0700630 }
Carl Shapiroea4dca82011-08-01 13:45:38 -0700631
Elliott Hughes37f7a402011-08-22 18:56:01 -0700632 static jboolean IsInstanceOf(JNIEnv* env, jobject jobj, jclass clazz) {
Elliott Hughescdf53122011-08-19 15:46:09 -0700633 ScopedJniThreadState ts(env);
Elliott Hughes37f7a402011-08-22 18:56:01 -0700634 CHECK_NE(static_cast<jclass>(NULL), clazz);
635 if (jobj == NULL) {
636 // NB. JNI is different from regular Java instanceof in this respect
637 return JNI_TRUE;
638 } else {
639 Object* obj = Decode<Object*>(ts, jobj);
640 Class* klass = Decode<Class*>(ts, clazz);
641 return Object::InstanceOf(obj, klass) ? JNI_TRUE : JNI_FALSE;
642 }
Elliott Hughescdf53122011-08-19 15:46:09 -0700643 }
Carl Shapiroea4dca82011-08-01 13:45:38 -0700644
Elliott Hughes37f7a402011-08-22 18:56:01 -0700645 static jint Throw(JNIEnv* env, jthrowable java_exception) {
646 ScopedJniThreadState ts(env);
Elliott Hughese5b0dc82011-08-23 09:59:02 -0700647 Throwable* exception = Decode<Throwable*>(ts, java_exception);
Elliott Hughes37f7a402011-08-22 18:56:01 -0700648 if (exception == NULL) {
649 return JNI_ERR;
650 }
651 ts.Self()->SetException(exception);
652 return JNI_OK;
653 }
654
Elliott Hughese5b0dc82011-08-23 09:59:02 -0700655 static jint ThrowNew(JNIEnv* env, jclass c, const char* msg) {
Elliott Hughes37f7a402011-08-22 18:56:01 -0700656 ScopedJniThreadState ts(env);
Elliott Hughese5b0dc82011-08-23 09:59:02 -0700657 // TODO: check for a pending exception to decide what constructor to call.
658 jmethodID mid = env->GetMethodID(c, "<init>", "(Ljava/lang/String;)V");
659 if (mid == NULL) {
660 return JNI_ERR;
661 }
662 jstring s = env->NewStringUTF(msg);
663 if (s == NULL) {
664 return JNI_ERR;
665 }
666
667 jvalue args[1];
668 args[0].l = s;
669 jthrowable exception = reinterpret_cast<jthrowable>(env->NewObjectA(c, mid, args));
670 if (exception == NULL) {
671 return JNI_ERR;
672 }
673
674 LOG(INFO) << "Throwing " << PrettyType(Decode<Throwable*>(ts, exception))
675 << ": " << msg;
676 ts.Self()->SetException(Decode<Throwable*>(ts, exception));
677
678 env->DeleteLocalRef(exception);
679 env->DeleteLocalRef(s);
680
Elliott Hughes37f7a402011-08-22 18:56:01 -0700681 return JNI_OK;
682 }
683
684 static jboolean ExceptionCheck(JNIEnv* env) {
685 ScopedJniThreadState ts(env);
686 return ts.Self()->IsExceptionPending() ? JNI_TRUE : JNI_FALSE;
687 }
688
689 static void ExceptionClear(JNIEnv* env) {
690 ScopedJniThreadState ts(env);
691 ts.Self()->ClearException();
692 }
693
694 static void ExceptionDescribe(JNIEnv* env) {
Elliott Hughescdf53122011-08-19 15:46:09 -0700695 ScopedJniThreadState ts(env);
696 UNIMPLEMENTED(FATAL);
Elliott Hughescdf53122011-08-19 15:46:09 -0700697 }
Carl Shapiroea4dca82011-08-01 13:45:38 -0700698
Elliott Hughescdf53122011-08-19 15:46:09 -0700699 static jthrowable ExceptionOccurred(JNIEnv* env) {
700 ScopedJniThreadState ts(env);
701 Object* exception = ts.Self()->GetException();
702 if (exception == NULL) {
703 return NULL;
704 } else {
705 // TODO: if adding a local reference failing causes the VM to abort
706 // then the following check will never occur.
707 jthrowable localException = AddLocalReference<jthrowable>(ts, exception);
708 if (localException == NULL) {
709 // We were unable to add a new local reference, and threw a new
710 // exception. We can't return "exception", because it's not a
711 // local reference. So we have to return NULL, indicating that
712 // there was no exception, even though it's pretty much raining
713 // exceptions in here.
714 LOG(WARNING) << "JNI WARNING: addLocal/exception combo";
715 }
716 return localException;
717 }
718 }
719
Elliott Hughescdf53122011-08-19 15:46:09 -0700720 static void FatalError(JNIEnv* env, const char* msg) {
721 ScopedJniThreadState ts(env);
722 LOG(FATAL) << "JNI FatalError called: " << msg;
723 }
724
725 static jint PushLocalFrame(JNIEnv* env, jint cap) {
726 ScopedJniThreadState ts(env);
727 UNIMPLEMENTED(WARNING) << "ignoring PushLocalFrame(" << cap << ")";
728 return JNI_OK;
729 }
730
731 static jobject PopLocalFrame(JNIEnv* env, jobject res) {
732 ScopedJniThreadState ts(env);
733 UNIMPLEMENTED(WARNING) << "ignoring PopLocalFrame " << res;
734 return res;
735 }
736
737 static jobject NewGlobalRef(JNIEnv* env, jobject obj) {
738 ScopedJniThreadState ts(env);
739 if (obj == NULL) {
740 return NULL;
741 }
742
743 JavaVMExt* vm = Runtime::Current()->GetJavaVM();
744 IndirectReferenceTable& globals = vm->globals;
745 MutexLock mu(vm->globals_lock);
746 IndirectRef ref = globals.Add(IRT_FIRST_SEGMENT, Decode<Object*>(ts, obj));
747 return reinterpret_cast<jobject>(ref);
748 }
749
750 static void DeleteGlobalRef(JNIEnv* env, jobject obj) {
751 ScopedJniThreadState ts(env);
752 if (obj == NULL) {
753 return;
754 }
755
756 JavaVMExt* vm = Runtime::Current()->GetJavaVM();
757 IndirectReferenceTable& globals = vm->globals;
758 MutexLock mu(vm->globals_lock);
759
760 if (!globals.Remove(IRT_FIRST_SEGMENT, obj)) {
761 LOG(WARNING) << "JNI WARNING: DeleteGlobalRef(" << obj << ") "
762 << "failed to find entry";
763 }
764 }
765
766 static jweak NewWeakGlobalRef(JNIEnv* env, jobject obj) {
767 ScopedJniThreadState ts(env);
768 return AddWeakGlobalReference(ts, Decode<Object*>(ts, obj));
769 }
770
771 static void DeleteWeakGlobalRef(JNIEnv* env, jweak obj) {
772 ScopedJniThreadState ts(env);
773 if (obj == NULL) {
774 return;
775 }
776
777 JavaVMExt* vm = Runtime::Current()->GetJavaVM();
778 IndirectReferenceTable& weak_globals = vm->weak_globals;
779 MutexLock mu(vm->weak_globals_lock);
780
781 if (!weak_globals.Remove(IRT_FIRST_SEGMENT, obj)) {
782 LOG(WARNING) << "JNI WARNING: DeleteWeakGlobalRef(" << obj << ") "
783 << "failed to find entry";
784 }
785 }
786
787 static jobject NewLocalRef(JNIEnv* env, jobject obj) {
788 ScopedJniThreadState ts(env);
789 if (obj == NULL) {
790 return NULL;
791 }
792
793 IndirectReferenceTable& locals = ts.Env()->locals;
794
795 uint32_t cookie = IRT_FIRST_SEGMENT; // TODO
796 IndirectRef ref = locals.Add(cookie, Decode<Object*>(ts, obj));
797 return reinterpret_cast<jobject>(ref);
798 }
799
800 static void DeleteLocalRef(JNIEnv* env, jobject obj) {
801 ScopedJniThreadState ts(env);
802 if (obj == NULL) {
803 return;
804 }
805
806 IndirectReferenceTable& locals = ts.Env()->locals;
807
808 uint32_t cookie = IRT_FIRST_SEGMENT; // TODO
809 if (!locals.Remove(cookie, obj)) {
810 // Attempting to delete a local reference that is not in the
811 // topmost local reference frame is a no-op. DeleteLocalRef returns
812 // void and doesn't throw any exceptions, but we should probably
813 // complain about it so the user will notice that things aren't
814 // going quite the way they expect.
815 LOG(WARNING) << "JNI WARNING: DeleteLocalRef(" << obj << ") "
816 << "failed to find entry";
817 }
818 }
819
820 static jboolean IsSameObject(JNIEnv* env, jobject obj1, jobject obj2) {
821 ScopedJniThreadState ts(env);
822 return (Decode<Object*>(ts, obj1) == Decode<Object*>(ts, obj2))
823 ? JNI_TRUE : JNI_FALSE;
824 }
825
826 static jint EnsureLocalCapacity(JNIEnv* env, jint) {
827 ScopedJniThreadState ts(env);
828 UNIMPLEMENTED(FATAL);
829 return 0;
830 }
831
Elliott Hughes885c3bd2011-08-22 16:59:20 -0700832 static jobject AllocObject(JNIEnv* env, jclass java_class) {
Elliott Hughescdf53122011-08-19 15:46:09 -0700833 ScopedJniThreadState ts(env);
Elliott Hughes885c3bd2011-08-22 16:59:20 -0700834 Class* c = Decode<Class*>(ts, java_class);
835 if (!Runtime::Current()->GetClassLinker()->EnsureInitialized(c)) {
836 return NULL;
837 }
838 return AddLocalReference<jobject>(ts, c->NewInstance());
Elliott Hughescdf53122011-08-19 15:46:09 -0700839 }
840
841 static jobject NewObject(JNIEnv* env, jclass clazz, jmethodID methodID, ...) {
842 ScopedJniThreadState ts(env);
843 va_list args;
844 va_start(args, methodID);
845 jobject result = NewObjectV(env, clazz, methodID, args);
846 va_end(args);
847 return result;
848 }
849
Elliott Hughes885c3bd2011-08-22 16:59:20 -0700850 static jobject NewObjectV(JNIEnv* env, jclass java_class, jmethodID methodID, va_list args) {
Elliott Hughescdf53122011-08-19 15:46:09 -0700851 ScopedJniThreadState ts(env);
Elliott Hughes885c3bd2011-08-22 16:59:20 -0700852 Class* c = Decode<Class*>(ts, java_class);
853 if (!Runtime::Current()->GetClassLinker()->EnsureInitialized(c)) {
854 return NULL;
855 }
856 Object* result = c->NewInstance();
Elliott Hughescdf53122011-08-19 15:46:09 -0700857 jobject local_result = AddLocalReference<jobject>(ts, result);
Elliott Hughes885c3bd2011-08-22 16:59:20 -0700858 CallNonvirtualVoidMethodV(env, local_result, java_class, methodID, args);
Elliott Hughescdf53122011-08-19 15:46:09 -0700859 return local_result;
860 }
861
Elliott Hughes885c3bd2011-08-22 16:59:20 -0700862 static jobject NewObjectA(JNIEnv* env, jclass java_class, jmethodID methodID, jvalue* args) {
Elliott Hughescdf53122011-08-19 15:46:09 -0700863 ScopedJniThreadState ts(env);
Elliott Hughes885c3bd2011-08-22 16:59:20 -0700864 Class* c = Decode<Class*>(ts, java_class);
865 if (!Runtime::Current()->GetClassLinker()->EnsureInitialized(c)) {
866 return NULL;
867 }
868 Object* result = c->NewInstance();
Elliott Hughescdf53122011-08-19 15:46:09 -0700869 jobject local_result = AddLocalReference<jobjectArray>(ts, result);
Elliott Hughes885c3bd2011-08-22 16:59:20 -0700870 CallNonvirtualVoidMethodA(env, local_result, java_class, methodID, args);
Elliott Hughescdf53122011-08-19 15:46:09 -0700871 return local_result;
872 }
873
Elliott Hughescdf53122011-08-19 15:46:09 -0700874 static jmethodID GetMethodID(JNIEnv* env, jclass c, const char* name, const char* sig) {
875 ScopedJniThreadState ts(env);
876 return FindMethodID(ts, c, name, sig, false);
877 }
878
879 static jmethodID GetStaticMethodID(JNIEnv* env, jclass c, const char* name, const char* sig) {
880 ScopedJniThreadState ts(env);
881 return FindMethodID(ts, c, name, sig, true);
882 }
883
884 static jobject CallObjectMethod(JNIEnv* env, jobject obj, jmethodID methodID, ...) {
885 ScopedJniThreadState ts(env);
886 UNIMPLEMENTED(FATAL);
887 return NULL;
888 }
889
890 static jobject CallObjectMethodV(JNIEnv* env,
891 jobject obj, jmethodID methodID, va_list args) {
892 ScopedJniThreadState ts(env);
893 UNIMPLEMENTED(FATAL);
894 return NULL;
895 }
896
897 static jobject CallObjectMethodA(JNIEnv* env,
898 jobject obj, jmethodID methodID, jvalue* args) {
899 ScopedJniThreadState ts(env);
900 UNIMPLEMENTED(FATAL);
901 return NULL;
902 }
903
904 static jboolean CallBooleanMethod(JNIEnv* env, jobject obj, jmethodID methodID, ...) {
905 ScopedJniThreadState ts(env);
906 UNIMPLEMENTED(FATAL);
907 return JNI_FALSE;
908 }
909
910 static jboolean CallBooleanMethodV(JNIEnv* env,
911 jobject obj, jmethodID methodID, va_list args) {
912 ScopedJniThreadState ts(env);
913 UNIMPLEMENTED(FATAL);
914 return JNI_FALSE;
915 }
916
917 static jboolean CallBooleanMethodA(JNIEnv* env,
918 jobject obj, jmethodID methodID, jvalue* args) {
919 ScopedJniThreadState ts(env);
920 UNIMPLEMENTED(FATAL);
921 return JNI_FALSE;
922 }
923
924 static jbyte CallByteMethod(JNIEnv* env, jobject obj, jmethodID methodID, ...) {
925 ScopedJniThreadState ts(env);
926 UNIMPLEMENTED(FATAL);
927 return 0;
928 }
929
930 static jbyte CallByteMethodV(JNIEnv* env,
931 jobject obj, jmethodID methodID, va_list args) {
932 ScopedJniThreadState ts(env);
933 UNIMPLEMENTED(FATAL);
934 return 0;
935 }
936
937 static jbyte CallByteMethodA(JNIEnv* env,
938 jobject obj, jmethodID methodID, jvalue* args) {
939 ScopedJniThreadState ts(env);
940 UNIMPLEMENTED(FATAL);
941 return 0;
942 }
943
944 static jchar CallCharMethod(JNIEnv* env, jobject obj, jmethodID methodID, ...) {
945 ScopedJniThreadState ts(env);
946 UNIMPLEMENTED(FATAL);
947 return 0;
948 }
949
950 static jchar CallCharMethodV(JNIEnv* env,
951 jobject obj, jmethodID methodID, va_list args) {
952 ScopedJniThreadState ts(env);
953 UNIMPLEMENTED(FATAL);
954 return 0;
955 }
956
957 static jchar CallCharMethodA(JNIEnv* env,
958 jobject obj, jmethodID methodID, jvalue* args) {
959 ScopedJniThreadState ts(env);
960 UNIMPLEMENTED(FATAL);
961 return 0;
962 }
963
964 static jshort CallShortMethod(JNIEnv* env, jobject obj, jmethodID methodID, ...) {
965 ScopedJniThreadState ts(env);
966 UNIMPLEMENTED(FATAL);
967 return 0;
968 }
969
970 static jshort CallShortMethodV(JNIEnv* env,
971 jobject obj, jmethodID methodID, va_list args) {
972 ScopedJniThreadState ts(env);
973 UNIMPLEMENTED(FATAL);
974 return 0;
975 }
976
977 static jshort CallShortMethodA(JNIEnv* env,
978 jobject obj, jmethodID methodID, jvalue* args) {
979 ScopedJniThreadState ts(env);
980 UNIMPLEMENTED(FATAL);
981 return 0;
982 }
983
984 static jint CallIntMethod(JNIEnv* env, jobject obj, jmethodID methodID, ...) {
985 ScopedJniThreadState ts(env);
986 UNIMPLEMENTED(FATAL);
987 return 0;
988 }
989
990 static jint CallIntMethodV(JNIEnv* env,
991 jobject obj, jmethodID methodID, va_list args) {
992 ScopedJniThreadState ts(env);
993 UNIMPLEMENTED(FATAL);
994 return 0;
995 }
996
997 static jint CallIntMethodA(JNIEnv* env,
998 jobject obj, jmethodID methodID, jvalue* args) {
999 ScopedJniThreadState ts(env);
1000 UNIMPLEMENTED(FATAL);
1001 return 0;
1002 }
1003
1004 static jlong CallLongMethod(JNIEnv* env, jobject obj, jmethodID methodID, ...) {
1005 ScopedJniThreadState ts(env);
1006 UNIMPLEMENTED(FATAL);
1007 return 0;
1008 }
1009
1010 static jlong CallLongMethodV(JNIEnv* env,
1011 jobject obj, jmethodID methodID, va_list args) {
1012 ScopedJniThreadState ts(env);
1013 UNIMPLEMENTED(FATAL);
1014 return 0;
1015 }
1016
1017 static jlong CallLongMethodA(JNIEnv* env,
1018 jobject obj, jmethodID methodID, jvalue* args) {
1019 ScopedJniThreadState ts(env);
1020 UNIMPLEMENTED(FATAL);
1021 return 0;
1022 }
1023
1024 static jfloat CallFloatMethod(JNIEnv* env, jobject obj, jmethodID methodID, ...) {
1025 ScopedJniThreadState ts(env);
1026 UNIMPLEMENTED(FATAL);
1027 return 0;
1028 }
1029
1030 static jfloat CallFloatMethodV(JNIEnv* env,
1031 jobject obj, jmethodID methodID, va_list args) {
1032 ScopedJniThreadState ts(env);
1033 UNIMPLEMENTED(FATAL);
1034 return 0;
1035 }
1036
1037 static jfloat CallFloatMethodA(JNIEnv* env,
1038 jobject obj, jmethodID methodID, jvalue* args) {
1039 ScopedJniThreadState ts(env);
1040 UNIMPLEMENTED(FATAL);
1041 return 0;
1042 }
1043
1044 static jdouble CallDoubleMethod(JNIEnv* env, jobject obj, jmethodID methodID, ...) {
1045 ScopedJniThreadState ts(env);
1046 UNIMPLEMENTED(FATAL);
1047 return 0;
1048 }
1049
1050 static jdouble CallDoubleMethodV(JNIEnv* env,
1051 jobject obj, jmethodID methodID, va_list args) {
1052 ScopedJniThreadState ts(env);
1053 UNIMPLEMENTED(FATAL);
1054 return 0;
1055 }
1056
1057 static jdouble CallDoubleMethodA(JNIEnv* env,
1058 jobject obj, jmethodID methodID, jvalue* args) {
1059 ScopedJniThreadState ts(env);
1060 UNIMPLEMENTED(FATAL);
1061 return 0;
1062 }
1063
1064 static void CallVoidMethod(JNIEnv* env, jobject obj, jmethodID methodID, ...) {
1065 ScopedJniThreadState ts(env);
1066 UNIMPLEMENTED(FATAL);
1067 }
1068
1069 static void CallVoidMethodV(JNIEnv* env, jobject obj,
1070 jmethodID methodID, va_list args) {
1071 ScopedJniThreadState ts(env);
1072 UNIMPLEMENTED(FATAL);
1073 }
1074
1075 static void CallVoidMethodA(JNIEnv* env, jobject obj,
1076 jmethodID methodID, jvalue* args) {
1077 ScopedJniThreadState ts(env);
1078 UNIMPLEMENTED(FATAL);
1079 }
1080
1081 static jobject CallNonvirtualObjectMethod(JNIEnv* env,
1082 jobject obj, jclass clazz, jmethodID methodID, ...) {
1083 ScopedJniThreadState ts(env);
1084 va_list ap;
1085 va_start(ap, methodID);
1086 JValue result = InvokeWithVarArgs(ts, obj, methodID, ap);
1087 jobject local_result = AddLocalReference<jobject>(ts, result.l);
1088 va_end(ap);
1089 return local_result;
1090 }
1091
1092 static jobject CallNonvirtualObjectMethodV(JNIEnv* env,
1093 jobject obj, jclass clazz, jmethodID methodID, va_list args) {
1094 ScopedJniThreadState ts(env);
1095 JValue result = InvokeWithVarArgs(ts, obj, methodID, args);
1096 return AddLocalReference<jobject>(ts, result.l);
1097 }
1098
1099 static jobject CallNonvirtualObjectMethodA(JNIEnv* env,
1100 jobject obj, jclass clazz, jmethodID methodID, jvalue* args) {
1101 ScopedJniThreadState ts(env);
1102 JValue result = InvokeWithJValues(ts, obj, methodID, args);
1103 return AddLocalReference<jobject>(ts, result.l);
1104 }
1105
1106 static jboolean CallNonvirtualBooleanMethod(JNIEnv* env,
1107 jobject obj, jclass clazz, jmethodID methodID, ...) {
1108 ScopedJniThreadState ts(env);
1109 va_list ap;
1110 va_start(ap, methodID);
1111 JValue result = InvokeWithVarArgs(ts, obj, methodID, ap);
1112 va_end(ap);
1113 return result.z;
1114 }
1115
1116 static jboolean CallNonvirtualBooleanMethodV(JNIEnv* env,
1117 jobject obj, jclass clazz, jmethodID methodID, va_list args) {
1118 ScopedJniThreadState ts(env);
1119 return InvokeWithVarArgs(ts, obj, methodID, args).z;
1120 }
1121
1122 static jboolean CallNonvirtualBooleanMethodA(JNIEnv* env,
1123 jobject obj, jclass clazz, jmethodID methodID, jvalue* args) {
1124 ScopedJniThreadState ts(env);
1125 return InvokeWithJValues(ts, obj, methodID, args).z;
1126 }
1127
1128 static jbyte CallNonvirtualByteMethod(JNIEnv* env,
1129 jobject obj, jclass clazz, jmethodID methodID, ...) {
1130 ScopedJniThreadState ts(env);
1131 va_list ap;
1132 va_start(ap, methodID);
1133 JValue result = InvokeWithVarArgs(ts, obj, methodID, ap);
1134 va_end(ap);
1135 return result.b;
1136 }
1137
1138 static jbyte CallNonvirtualByteMethodV(JNIEnv* env,
1139 jobject obj, jclass clazz, jmethodID methodID, va_list args) {
1140 ScopedJniThreadState ts(env);
1141 return InvokeWithVarArgs(ts, obj, methodID, args).b;
1142 }
1143
1144 static jbyte CallNonvirtualByteMethodA(JNIEnv* env,
1145 jobject obj, jclass clazz, jmethodID methodID, jvalue* args) {
1146 ScopedJniThreadState ts(env);
1147 return InvokeWithJValues(ts, obj, methodID, args).b;
1148 }
1149
1150 static jchar CallNonvirtualCharMethod(JNIEnv* env,
1151 jobject obj, jclass clazz, jmethodID methodID, ...) {
1152 ScopedJniThreadState ts(env);
1153 va_list ap;
1154 va_start(ap, methodID);
1155 JValue result = InvokeWithVarArgs(ts, obj, methodID, ap);
1156 va_end(ap);
1157 return result.c;
1158 }
1159
1160 static jchar CallNonvirtualCharMethodV(JNIEnv* env,
1161 jobject obj, jclass clazz, jmethodID methodID, va_list args) {
1162 ScopedJniThreadState ts(env);
1163 return InvokeWithVarArgs(ts, obj, methodID, args).c;
1164 }
1165
1166 static jchar CallNonvirtualCharMethodA(JNIEnv* env,
1167 jobject obj, jclass clazz, jmethodID methodID, jvalue* args) {
1168 ScopedJniThreadState ts(env);
1169 return InvokeWithJValues(ts, obj, methodID, args).c;
1170 }
1171
1172 static jshort CallNonvirtualShortMethod(JNIEnv* env,
1173 jobject obj, jclass clazz, jmethodID methodID, ...) {
1174 ScopedJniThreadState ts(env);
1175 va_list ap;
1176 va_start(ap, methodID);
1177 JValue result = InvokeWithVarArgs(ts, obj, methodID, ap);
1178 va_end(ap);
1179 return result.s;
1180 }
1181
1182 static jshort CallNonvirtualShortMethodV(JNIEnv* env,
1183 jobject obj, jclass clazz, jmethodID methodID, va_list args) {
1184 ScopedJniThreadState ts(env);
1185 return InvokeWithVarArgs(ts, obj, methodID, args).s;
1186 }
1187
1188 static jshort CallNonvirtualShortMethodA(JNIEnv* env,
1189 jobject obj, jclass clazz, jmethodID methodID, jvalue* args) {
1190 ScopedJniThreadState ts(env);
1191 return InvokeWithJValues(ts, obj, methodID, args).s;
1192 }
1193
1194 static jint CallNonvirtualIntMethod(JNIEnv* env,
1195 jobject obj, jclass clazz, jmethodID methodID, ...) {
1196 ScopedJniThreadState ts(env);
1197 va_list ap;
1198 va_start(ap, methodID);
1199 JValue result = InvokeWithVarArgs(ts, obj, methodID, ap);
1200 va_end(ap);
1201 return result.i;
1202 }
1203
1204 static jint CallNonvirtualIntMethodV(JNIEnv* env,
1205 jobject obj, jclass clazz, jmethodID methodID, va_list args) {
1206 ScopedJniThreadState ts(env);
1207 return InvokeWithVarArgs(ts, obj, methodID, args).i;
1208 }
1209
1210 static jint CallNonvirtualIntMethodA(JNIEnv* env,
1211 jobject obj, jclass clazz, jmethodID methodID, jvalue* args) {
1212 ScopedJniThreadState ts(env);
1213 return InvokeWithJValues(ts, obj, methodID, args).i;
1214 }
1215
1216 static jlong CallNonvirtualLongMethod(JNIEnv* env,
1217 jobject obj, jclass clazz, jmethodID methodID, ...) {
1218 ScopedJniThreadState ts(env);
1219 va_list ap;
1220 va_start(ap, methodID);
1221 JValue result = InvokeWithVarArgs(ts, obj, methodID, ap);
1222 va_end(ap);
1223 return result.j;
1224 }
1225
1226 static jlong CallNonvirtualLongMethodV(JNIEnv* env,
1227 jobject obj, jclass clazz, jmethodID methodID, va_list args) {
1228 ScopedJniThreadState ts(env);
1229 return InvokeWithVarArgs(ts, obj, methodID, args).j;
1230 }
1231
1232 static jlong CallNonvirtualLongMethodA(JNIEnv* env,
1233 jobject obj, jclass clazz, jmethodID methodID, jvalue* args) {
1234 ScopedJniThreadState ts(env);
1235 return InvokeWithJValues(ts, obj, methodID, args).j;
1236 }
1237
1238 static jfloat CallNonvirtualFloatMethod(JNIEnv* env,
1239 jobject obj, jclass clazz, jmethodID methodID, ...) {
1240 ScopedJniThreadState ts(env);
1241 va_list ap;
1242 va_start(ap, methodID);
1243 JValue result = InvokeWithVarArgs(ts, obj, methodID, ap);
1244 va_end(ap);
1245 return result.f;
1246 }
1247
1248 static jfloat CallNonvirtualFloatMethodV(JNIEnv* env,
1249 jobject obj, jclass clazz, jmethodID methodID, va_list args) {
1250 ScopedJniThreadState ts(env);
1251 return InvokeWithVarArgs(ts, obj, methodID, args).f;
1252 }
1253
1254 static jfloat CallNonvirtualFloatMethodA(JNIEnv* env,
1255 jobject obj, jclass clazz, jmethodID methodID, jvalue* args) {
1256 ScopedJniThreadState ts(env);
1257 return InvokeWithJValues(ts, obj, methodID, args).f;
1258 }
1259
1260 static jdouble CallNonvirtualDoubleMethod(JNIEnv* env,
1261 jobject obj, jclass clazz, jmethodID methodID, ...) {
1262 ScopedJniThreadState ts(env);
1263 va_list ap;
1264 va_start(ap, methodID);
1265 JValue result = InvokeWithVarArgs(ts, obj, methodID, ap);
1266 va_end(ap);
1267 return result.d;
1268 }
1269
1270 static jdouble CallNonvirtualDoubleMethodV(JNIEnv* env,
1271 jobject obj, jclass clazz, jmethodID methodID, va_list args) {
1272 ScopedJniThreadState ts(env);
1273 return InvokeWithVarArgs(ts, obj, methodID, args).d;
1274 }
1275
1276 static jdouble CallNonvirtualDoubleMethodA(JNIEnv* env,
1277 jobject obj, jclass clazz, jmethodID methodID, jvalue* args) {
1278 ScopedJniThreadState ts(env);
1279 return InvokeWithJValues(ts, obj, methodID, args).d;
1280 }
1281
1282 static void CallNonvirtualVoidMethod(JNIEnv* env,
1283 jobject obj, jclass clazz, jmethodID methodID, ...) {
1284 ScopedJniThreadState ts(env);
1285 va_list ap;
1286 va_start(ap, methodID);
1287 InvokeWithVarArgs(ts, obj, methodID, ap);
1288 va_end(ap);
1289 }
1290
1291 static void CallNonvirtualVoidMethodV(JNIEnv* env,
1292 jobject obj, jclass clazz, jmethodID methodID, va_list args) {
1293 ScopedJniThreadState ts(env);
1294 InvokeWithVarArgs(ts, obj, methodID, args);
1295 }
1296
1297 static void CallNonvirtualVoidMethodA(JNIEnv* env,
1298 jobject obj, jclass clazz, jmethodID methodID, jvalue* args) {
1299 ScopedJniThreadState ts(env);
1300 InvokeWithJValues(ts, obj, methodID, args);
1301 }
1302
1303 static jfieldID GetFieldID(JNIEnv* env,
1304 jclass c, const char* name, const char* sig) {
1305 ScopedJniThreadState ts(env);
1306 return FindFieldID(ts, c, name, sig, false);
1307 }
Carl Shapiroea4dca82011-08-01 13:45:38 -07001308
1309
Elliott Hughescdf53122011-08-19 15:46:09 -07001310 static jfieldID GetStaticFieldID(JNIEnv* env,
1311 jclass c, const char* name, const char* sig) {
1312 ScopedJniThreadState ts(env);
1313 return FindFieldID(ts, c, name, sig, true);
1314 }
Carl Shapiroea4dca82011-08-01 13:45:38 -07001315
Elliott Hughes885c3bd2011-08-22 16:59:20 -07001316 static jobject GetObjectField(JNIEnv* env, jobject obj, jfieldID fid) {
Elliott Hughescdf53122011-08-19 15:46:09 -07001317 ScopedJniThreadState ts(env);
Elliott Hughes885c3bd2011-08-22 16:59:20 -07001318 Object* o = Decode<Object*>(ts, obj);
1319 Field* f = DecodeField(ts, fid);
1320 return AddLocalReference<jobject>(ts, f->GetObject(o));
Elliott Hughescdf53122011-08-19 15:46:09 -07001321 }
Carl Shapiroea4dca82011-08-01 13:45:38 -07001322
Elliott Hughes885c3bd2011-08-22 16:59:20 -07001323 static jobject GetStaticObjectField(JNIEnv* env, jclass, jfieldID fid) {
Elliott Hughescdf53122011-08-19 15:46:09 -07001324 ScopedJniThreadState ts(env);
Elliott Hughes885c3bd2011-08-22 16:59:20 -07001325 Field* f = DecodeField(ts, fid);
1326 return AddLocalReference<jobject>(ts, f->GetObject(NULL));
Elliott Hughescdf53122011-08-19 15:46:09 -07001327 }
1328
Elliott Hughes885c3bd2011-08-22 16:59:20 -07001329 static void SetObjectField(JNIEnv* env, jobject java_object, jfieldID fid, jobject java_value) {
Elliott Hughescdf53122011-08-19 15:46:09 -07001330 ScopedJniThreadState ts(env);
Elliott Hughes885c3bd2011-08-22 16:59:20 -07001331 Object* o = Decode<Object*>(ts, java_object);
1332 Object* v = Decode<Object*>(ts, java_value);
1333 Field* f = DecodeField(ts, fid);
1334 f->SetObject(o, v);
Elliott Hughescdf53122011-08-19 15:46:09 -07001335 }
1336
Elliott Hughes885c3bd2011-08-22 16:59:20 -07001337 static void SetStaticObjectField(JNIEnv* env, jclass, jfieldID fid, jobject java_value) {
Elliott Hughescdf53122011-08-19 15:46:09 -07001338 ScopedJniThreadState ts(env);
Elliott Hughes885c3bd2011-08-22 16:59:20 -07001339 Object* v = Decode<Object*>(ts, java_value);
1340 Field* f = DecodeField(ts, fid);
1341 f->SetObject(NULL, v);
Elliott Hughescdf53122011-08-19 15:46:09 -07001342 }
1343
Elliott Hughes885c3bd2011-08-22 16:59:20 -07001344#define GET_PRIMITIVE_FIELD(fn, instance) \
1345 ScopedJniThreadState ts(env); \
1346 Object* o = Decode<Object*>(ts, instance); \
1347 Field* f = DecodeField(ts, fid); \
1348 return f->fn(o)
1349
1350#define SET_PRIMITIVE_FIELD(fn, instance, value) \
1351 ScopedJniThreadState ts(env); \
1352 Object* o = Decode<Object*>(ts, instance); \
1353 Field* f = DecodeField(ts, fid); \
1354 f->fn(o, value)
1355
1356 static jboolean GetBooleanField(JNIEnv* env, jobject obj, jfieldID fid) {
1357 GET_PRIMITIVE_FIELD(GetBoolean, obj);
Elliott Hughescdf53122011-08-19 15:46:09 -07001358 }
1359
Elliott Hughes885c3bd2011-08-22 16:59:20 -07001360 static jbyte GetByteField(JNIEnv* env, jobject obj, jfieldID fid) {
1361 GET_PRIMITIVE_FIELD(GetByte, obj);
Elliott Hughescdf53122011-08-19 15:46:09 -07001362 }
1363
Elliott Hughes885c3bd2011-08-22 16:59:20 -07001364 static jchar GetCharField(JNIEnv* env, jobject obj, jfieldID fid) {
1365 GET_PRIMITIVE_FIELD(GetChar, obj);
Elliott Hughescdf53122011-08-19 15:46:09 -07001366 }
1367
Elliott Hughes885c3bd2011-08-22 16:59:20 -07001368 static jshort GetShortField(JNIEnv* env, jobject obj, jfieldID fid) {
1369 GET_PRIMITIVE_FIELD(GetShort, obj);
Elliott Hughescdf53122011-08-19 15:46:09 -07001370 }
1371
Elliott Hughes885c3bd2011-08-22 16:59:20 -07001372 static jint GetIntField(JNIEnv* env, jobject obj, jfieldID fid) {
1373 GET_PRIMITIVE_FIELD(GetInt, obj);
Elliott Hughescdf53122011-08-19 15:46:09 -07001374 }
1375
Elliott Hughes885c3bd2011-08-22 16:59:20 -07001376 static jlong GetLongField(JNIEnv* env, jobject obj, jfieldID fid) {
1377 GET_PRIMITIVE_FIELD(GetLong, obj);
Elliott Hughescdf53122011-08-19 15:46:09 -07001378 }
1379
Elliott Hughes885c3bd2011-08-22 16:59:20 -07001380 static jfloat GetFloatField(JNIEnv* env, jobject obj, jfieldID fid) {
1381 GET_PRIMITIVE_FIELD(GetFloat, obj);
Elliott Hughescdf53122011-08-19 15:46:09 -07001382 }
1383
Elliott Hughes885c3bd2011-08-22 16:59:20 -07001384 static jdouble GetDoubleField(JNIEnv* env, jobject obj, jfieldID fid) {
1385 GET_PRIMITIVE_FIELD(GetDouble, obj);
Elliott Hughescdf53122011-08-19 15:46:09 -07001386 }
1387
Elliott Hughes885c3bd2011-08-22 16:59:20 -07001388 static jboolean GetStaticBooleanField(JNIEnv* env, jclass clazz, jfieldID fid) {
1389 GET_PRIMITIVE_FIELD(GetBoolean, NULL);
Elliott Hughescdf53122011-08-19 15:46:09 -07001390 }
1391
Elliott Hughes885c3bd2011-08-22 16:59:20 -07001392 static jbyte GetStaticByteField(JNIEnv* env, jclass clazz, jfieldID fid) {
1393 GET_PRIMITIVE_FIELD(GetByte, NULL);
Elliott Hughescdf53122011-08-19 15:46:09 -07001394 }
1395
Elliott Hughes885c3bd2011-08-22 16:59:20 -07001396 static jchar GetStaticCharField(JNIEnv* env, jclass clazz, jfieldID fid) {
1397 GET_PRIMITIVE_FIELD(GetChar, NULL);
Elliott Hughescdf53122011-08-19 15:46:09 -07001398 }
1399
Elliott Hughes885c3bd2011-08-22 16:59:20 -07001400 static jshort GetStaticShortField(JNIEnv* env, jclass clazz, jfieldID fid) {
1401 GET_PRIMITIVE_FIELD(GetShort, NULL);
Elliott Hughescdf53122011-08-19 15:46:09 -07001402 }
1403
Elliott Hughes885c3bd2011-08-22 16:59:20 -07001404 static jint GetStaticIntField(JNIEnv* env, jclass clazz, jfieldID fid) {
1405 GET_PRIMITIVE_FIELD(GetInt, NULL);
Elliott Hughescdf53122011-08-19 15:46:09 -07001406 }
1407
Elliott Hughes885c3bd2011-08-22 16:59:20 -07001408 static jlong GetStaticLongField(JNIEnv* env, jclass clazz, jfieldID fid) {
1409 GET_PRIMITIVE_FIELD(GetLong, NULL);
1410 }
1411
1412 static jfloat GetStaticFloatField(JNIEnv* env, jclass clazz, jfieldID fid) {
1413 GET_PRIMITIVE_FIELD(GetFloat, NULL);
1414 }
1415
1416 static jdouble GetStaticDoubleField(JNIEnv* env, jclass clazz, jfieldID fid) {
1417 GET_PRIMITIVE_FIELD(GetDouble, NULL);
1418 }
1419
1420 static void SetBooleanField(JNIEnv* env, jobject obj, jfieldID fid, jboolean v) {
1421 SET_PRIMITIVE_FIELD(SetBoolean, obj, v);
1422 }
1423
1424 static void SetByteField(JNIEnv* env, jobject obj, jfieldID fid, jbyte v) {
1425 SET_PRIMITIVE_FIELD(SetByte, obj, v);
1426 }
1427
1428 static void SetCharField(JNIEnv* env, jobject obj, jfieldID fid, jchar v) {
1429 SET_PRIMITIVE_FIELD(SetChar, obj, v);
1430 }
1431
1432 static void SetFloatField(JNIEnv* env, jobject obj, jfieldID fid, jfloat v) {
1433 SET_PRIMITIVE_FIELD(SetFloat, obj, v);
1434 }
1435
1436 static void SetDoubleField(JNIEnv* env, jobject obj, jfieldID fid, jdouble v) {
1437 SET_PRIMITIVE_FIELD(SetDouble, obj, v);
1438 }
1439
1440 static void SetIntField(JNIEnv* env, jobject obj, jfieldID fid, jint v) {
1441 SET_PRIMITIVE_FIELD(SetInt, obj, v);
1442 }
1443
1444 static void SetLongField(JNIEnv* env, jobject obj, jfieldID fid, jlong v) {
1445 SET_PRIMITIVE_FIELD(SetLong, obj, v);
1446 }
1447
1448 static void SetShortField(JNIEnv* env, jobject obj, jfieldID fid, jshort v) {
1449 SET_PRIMITIVE_FIELD(SetShort, obj, v);
1450 }
1451
1452 static void SetStaticBooleanField(JNIEnv* env, jclass, jfieldID fid, jboolean v) {
1453 SET_PRIMITIVE_FIELD(SetBoolean, NULL, v);
1454 }
1455
1456 static void SetStaticByteField(JNIEnv* env, jclass, jfieldID fid, jbyte v) {
1457 SET_PRIMITIVE_FIELD(SetByte, NULL, v);
1458 }
1459
1460 static void SetStaticCharField(JNIEnv* env, jclass, jfieldID fid, jchar v) {
1461 SET_PRIMITIVE_FIELD(SetChar, NULL, v);
1462 }
1463
1464 static void SetStaticFloatField(JNIEnv* env, jclass, jfieldID fid, jfloat v) {
1465 SET_PRIMITIVE_FIELD(SetFloat, NULL, v);
1466 }
1467
1468 static void SetStaticDoubleField(JNIEnv* env, jclass, jfieldID fid, jdouble v) {
1469 SET_PRIMITIVE_FIELD(SetDouble, NULL, v);
1470 }
1471
1472 static void SetStaticIntField(JNIEnv* env, jclass, jfieldID fid, jint v) {
1473 SET_PRIMITIVE_FIELD(SetInt, NULL, v);
1474 }
1475
1476 static void SetStaticLongField(JNIEnv* env, jclass, jfieldID fid, jlong v) {
1477 SET_PRIMITIVE_FIELD(SetLong, NULL, v);
1478 }
1479
1480 static void SetStaticShortField(JNIEnv* env, jclass, jfieldID fid, jshort v) {
1481 SET_PRIMITIVE_FIELD(SetShort, NULL, v);
Elliott Hughescdf53122011-08-19 15:46:09 -07001482 }
1483
1484 static jobject CallStaticObjectMethod(JNIEnv* env,
1485 jclass clazz, jmethodID methodID, ...) {
1486 ScopedJniThreadState ts(env);
1487 va_list ap;
1488 va_start(ap, methodID);
1489 JValue result = InvokeWithVarArgs(ts, NULL, methodID, ap);
1490 jobject local_result = AddLocalReference<jobject>(ts, result.l);
1491 va_end(ap);
1492 return local_result;
1493 }
1494
1495 static jobject CallStaticObjectMethodV(JNIEnv* env,
1496 jclass clazz, jmethodID methodID, va_list args) {
1497 ScopedJniThreadState ts(env);
1498 JValue result = InvokeWithVarArgs(ts, NULL, methodID, args);
1499 return AddLocalReference<jobject>(ts, result.l);
1500 }
1501
1502 static jobject CallStaticObjectMethodA(JNIEnv* env,
1503 jclass clazz, jmethodID methodID, jvalue* args) {
1504 ScopedJniThreadState ts(env);
1505 JValue result = InvokeWithJValues(ts, NULL, methodID, args);
1506 return AddLocalReference<jobject>(ts, result.l);
1507 }
1508
1509 static jboolean CallStaticBooleanMethod(JNIEnv* env,
1510 jclass clazz, jmethodID methodID, ...) {
1511 ScopedJniThreadState ts(env);
1512 va_list ap;
1513 va_start(ap, methodID);
1514 JValue result = InvokeWithVarArgs(ts, NULL, methodID, ap);
1515 va_end(ap);
1516 return result.z;
1517 }
1518
1519 static jboolean CallStaticBooleanMethodV(JNIEnv* env,
1520 jclass clazz, jmethodID methodID, va_list args) {
1521 ScopedJniThreadState ts(env);
1522 return InvokeWithVarArgs(ts, NULL, methodID, args).z;
1523 }
1524
1525 static jboolean CallStaticBooleanMethodA(JNIEnv* env,
1526 jclass clazz, jmethodID methodID, jvalue* args) {
1527 ScopedJniThreadState ts(env);
1528 return InvokeWithJValues(ts, NULL, methodID, args).z;
1529 }
1530
1531 static jbyte CallStaticByteMethod(JNIEnv* env, jclass clazz, jmethodID methodID, ...) {
1532 ScopedJniThreadState ts(env);
1533 va_list ap;
1534 va_start(ap, methodID);
1535 JValue result = InvokeWithVarArgs(ts, NULL, methodID, ap);
1536 va_end(ap);
1537 return result.b;
1538 }
1539
1540 static jbyte CallStaticByteMethodV(JNIEnv* env,
1541 jclass clazz, jmethodID methodID, va_list args) {
1542 ScopedJniThreadState ts(env);
1543 return InvokeWithVarArgs(ts, NULL, methodID, args).b;
1544 }
1545
1546 static jbyte CallStaticByteMethodA(JNIEnv* env,
1547 jclass clazz, jmethodID methodID, jvalue* args) {
1548 ScopedJniThreadState ts(env);
1549 return InvokeWithJValues(ts, NULL, methodID, args).b;
1550 }
1551
1552 static jchar CallStaticCharMethod(JNIEnv* env, jclass clazz, jmethodID methodID, ...) {
1553 ScopedJniThreadState ts(env);
1554 va_list ap;
1555 va_start(ap, methodID);
1556 JValue result = InvokeWithVarArgs(ts, NULL, methodID, ap);
1557 va_end(ap);
1558 return result.c;
1559 }
1560
1561 static jchar CallStaticCharMethodV(JNIEnv* env,
1562 jclass clazz, jmethodID methodID, va_list args) {
1563 ScopedJniThreadState ts(env);
1564 return InvokeWithVarArgs(ts, NULL, methodID, args).c;
1565 }
1566
1567 static jchar CallStaticCharMethodA(JNIEnv* env,
1568 jclass clazz, jmethodID methodID, jvalue* args) {
1569 ScopedJniThreadState ts(env);
1570 return InvokeWithJValues(ts, NULL, methodID, args).c;
1571 }
1572
1573 static jshort CallStaticShortMethod(JNIEnv* env, jclass clazz, jmethodID methodID, ...) {
1574 ScopedJniThreadState ts(env);
1575 va_list ap;
1576 va_start(ap, methodID);
1577 JValue result = InvokeWithVarArgs(ts, NULL, methodID, ap);
1578 va_end(ap);
1579 return result.s;
1580 }
1581
1582 static jshort CallStaticShortMethodV(JNIEnv* env,
1583 jclass clazz, jmethodID methodID, va_list args) {
1584 ScopedJniThreadState ts(env);
1585 return InvokeWithVarArgs(ts, NULL, methodID, args).s;
1586 }
1587
1588 static jshort CallStaticShortMethodA(JNIEnv* env,
1589 jclass clazz, jmethodID methodID, jvalue* args) {
1590 ScopedJniThreadState ts(env);
1591 return InvokeWithJValues(ts, NULL, methodID, args).s;
1592 }
1593
1594 static jint CallStaticIntMethod(JNIEnv* env, jclass clazz, jmethodID methodID, ...) {
1595 ScopedJniThreadState ts(env);
1596 va_list ap;
1597 va_start(ap, methodID);
1598 JValue result = InvokeWithVarArgs(ts, NULL, methodID, ap);
1599 va_end(ap);
1600 return result.i;
1601 }
1602
1603 static jint CallStaticIntMethodV(JNIEnv* env,
1604 jclass clazz, jmethodID methodID, va_list args) {
1605 ScopedJniThreadState ts(env);
1606 return InvokeWithVarArgs(ts, NULL, methodID, args).i;
1607 }
1608
1609 static jint CallStaticIntMethodA(JNIEnv* env,
1610 jclass clazz, jmethodID methodID, jvalue* args) {
1611 ScopedJniThreadState ts(env);
1612 return InvokeWithJValues(ts, NULL, methodID, args).i;
1613 }
1614
1615 static jlong CallStaticLongMethod(JNIEnv* env, jclass clazz, jmethodID methodID, ...) {
1616 ScopedJniThreadState ts(env);
1617 va_list ap;
1618 va_start(ap, methodID);
1619 JValue result = InvokeWithVarArgs(ts, NULL, methodID, ap);
1620 va_end(ap);
1621 return result.j;
1622 }
1623
1624 static jlong CallStaticLongMethodV(JNIEnv* env,
1625 jclass clazz, jmethodID methodID, va_list args) {
1626 ScopedJniThreadState ts(env);
1627 return InvokeWithVarArgs(ts, NULL, methodID, args).j;
1628 }
1629
1630 static jlong CallStaticLongMethodA(JNIEnv* env,
1631 jclass clazz, jmethodID methodID, jvalue* args) {
1632 ScopedJniThreadState ts(env);
1633 return InvokeWithJValues(ts, NULL, methodID, args).j;
1634 }
1635
1636 static jfloat CallStaticFloatMethod(JNIEnv* env, jclass cls, jmethodID methodID, ...) {
1637 ScopedJniThreadState ts(env);
1638 va_list ap;
1639 va_start(ap, methodID);
1640 JValue result = InvokeWithVarArgs(ts, NULL, methodID, ap);
1641 va_end(ap);
1642 return result.f;
1643 }
1644
1645 static jfloat CallStaticFloatMethodV(JNIEnv* env,
1646 jclass clazz, jmethodID methodID, va_list args) {
1647 ScopedJniThreadState ts(env);
1648 return InvokeWithVarArgs(ts, NULL, methodID, args).f;
1649 }
1650
1651 static jfloat CallStaticFloatMethodA(JNIEnv* env,
1652 jclass clazz, jmethodID methodID, jvalue* args) {
1653 ScopedJniThreadState ts(env);
1654 return InvokeWithJValues(ts, NULL, methodID, args).f;
1655 }
1656
1657 static jdouble CallStaticDoubleMethod(JNIEnv* env, jclass cls, jmethodID methodID, ...) {
1658 ScopedJniThreadState ts(env);
1659 va_list ap;
1660 va_start(ap, methodID);
1661 JValue result = InvokeWithVarArgs(ts, NULL, methodID, ap);
1662 va_end(ap);
1663 return result.d;
1664 }
1665
1666 static jdouble CallStaticDoubleMethodV(JNIEnv* env,
1667 jclass clazz, jmethodID methodID, va_list args) {
1668 ScopedJniThreadState ts(env);
1669 return InvokeWithVarArgs(ts, NULL, methodID, args).d;
1670 }
1671
1672 static jdouble CallStaticDoubleMethodA(JNIEnv* env,
1673 jclass clazz, jmethodID methodID, jvalue* args) {
1674 ScopedJniThreadState ts(env);
1675 return InvokeWithJValues(ts, NULL, methodID, args).d;
1676 }
1677
1678 static void CallStaticVoidMethod(JNIEnv* env, jclass cls, jmethodID methodID, ...) {
1679 ScopedJniThreadState ts(env);
1680 va_list ap;
1681 va_start(ap, methodID);
1682 InvokeWithVarArgs(ts, NULL, methodID, ap);
1683 va_end(ap);
1684 }
1685
1686 static void CallStaticVoidMethodV(JNIEnv* env,
1687 jclass cls, jmethodID methodID, va_list args) {
1688 ScopedJniThreadState ts(env);
1689 InvokeWithVarArgs(ts, NULL, methodID, args);
1690 }
1691
1692 static void CallStaticVoidMethodA(JNIEnv* env,
1693 jclass cls, jmethodID methodID, jvalue* args) {
1694 ScopedJniThreadState ts(env);
1695 InvokeWithJValues(ts, NULL, methodID, args);
1696 }
1697
Elliott Hughes814e4032011-08-23 12:07:56 -07001698 static jstring NewString(JNIEnv* env, const jchar* chars, jsize char_count) {
Elliott Hughescdf53122011-08-19 15:46:09 -07001699 ScopedJniThreadState ts(env);
Elliott Hughes814e4032011-08-23 12:07:56 -07001700 if (chars == NULL && char_count == 0) {
1701 return NULL;
1702 }
1703 String* result = String::AllocFromUtf16(char_count, chars);
1704 return AddLocalReference<jstring>(ts, result);
Elliott Hughescdf53122011-08-19 15:46:09 -07001705 }
1706
1707 static jstring NewStringUTF(JNIEnv* env, const char* utf) {
1708 ScopedJniThreadState ts(env);
1709 if (utf == NULL) {
1710 return NULL;
1711 }
1712 String* result = String::AllocFromModifiedUtf8(utf);
1713 return AddLocalReference<jstring>(ts, result);
1714 }
1715
Elliott Hughes814e4032011-08-23 12:07:56 -07001716 static jsize GetStringLength(JNIEnv* env, jstring java_string) {
1717 ScopedJniThreadState ts(env);
1718 return Decode<String*>(ts, java_string)->GetLength();
1719 }
1720
1721 static jsize GetStringUTFLength(JNIEnv* env, jstring java_string) {
1722 ScopedJniThreadState ts(env);
1723 return Decode<String*>(ts, java_string)->GetUtfLength();
1724 }
1725
1726 static void GetStringRegion(JNIEnv* env, jstring str, jsize start, jsize len, jchar* buf) {
Elliott Hughescdf53122011-08-19 15:46:09 -07001727 ScopedJniThreadState ts(env);
1728 UNIMPLEMENTED(FATAL);
Elliott Hughes814e4032011-08-23 12:07:56 -07001729 }
1730
1731 static void GetStringUTFRegion(JNIEnv* env, jstring str, jsize start, jsize len, char* buf) {
1732 ScopedJniThreadState ts(env);
1733 UNIMPLEMENTED(FATAL);
1734 }
1735
1736 static const jchar* GetStringChars(JNIEnv* env, jstring str, jboolean* isCopy) {
1737 ScopedJniThreadState ts(env);
1738 UNIMPLEMENTED(FATAL);
1739 return NULL;
1740 }
1741
1742 static void ReleaseStringChars(JNIEnv* env, jstring str, const jchar* chars) {
1743 ScopedJniThreadState ts(env);
1744 UNIMPLEMENTED(FATAL);
Elliott Hughescdf53122011-08-19 15:46:09 -07001745 }
1746
1747 static const char* GetStringUTFChars(JNIEnv* env, jstring str, jboolean* isCopy) {
1748 ScopedJniThreadState ts(env);
1749 UNIMPLEMENTED(FATAL);
1750 return NULL;
1751 }
1752
1753 static void ReleaseStringUTFChars(JNIEnv* env, jstring str, const char* chars) {
1754 ScopedJniThreadState ts(env);
1755 UNIMPLEMENTED(FATAL);
1756 }
1757
Elliott Hughesbd935992011-08-22 11:59:34 -07001758 static jsize GetArrayLength(JNIEnv* env, jarray java_array) {
Elliott Hughescdf53122011-08-19 15:46:09 -07001759 ScopedJniThreadState ts(env);
Elliott Hughesbd935992011-08-22 11:59:34 -07001760 Object* obj = Decode<Object*>(ts, java_array);
1761 CHECK(obj->IsArray()); // TODO: ReportJniError
1762 Array* array = obj->AsArray();
1763 return array->GetLength();
Elliott Hughescdf53122011-08-19 15:46:09 -07001764 }
1765
Elliott Hughes814e4032011-08-23 12:07:56 -07001766 static jobject GetObjectArrayElement(JNIEnv* env, jobjectArray java_array, jsize index) {
Elliott Hughescdf53122011-08-19 15:46:09 -07001767 ScopedJniThreadState ts(env);
Elliott Hughes814e4032011-08-23 12:07:56 -07001768 ObjectArray<Object>* array = Decode<ObjectArray<Object>*>(ts, java_array);
1769 return AddLocalReference<jobject>(ts, array->Get(index));
Elliott Hughescdf53122011-08-19 15:46:09 -07001770 }
1771
1772 static void SetObjectArrayElement(JNIEnv* env,
1773 jobjectArray java_array, jsize index, jobject java_value) {
1774 ScopedJniThreadState ts(env);
1775 ObjectArray<Object>* array = Decode<ObjectArray<Object>*>(ts, java_array);
1776 Object* value = Decode<Object*>(ts, java_value);
1777 array->Set(index, value);
1778 }
1779
1780 static jbooleanArray NewBooleanArray(JNIEnv* env, jsize length) {
1781 ScopedJniThreadState ts(env);
1782 return NewPrimitiveArray<jbooleanArray, BooleanArray>(ts, length);
1783 }
1784
1785 static jbyteArray NewByteArray(JNIEnv* env, jsize length) {
1786 ScopedJniThreadState ts(env);
1787 return NewPrimitiveArray<jbyteArray, ByteArray>(ts, length);
1788 }
1789
1790 static jcharArray NewCharArray(JNIEnv* env, jsize length) {
1791 ScopedJniThreadState ts(env);
1792 return NewPrimitiveArray<jcharArray, CharArray>(ts, length);
1793 }
1794
1795 static jdoubleArray NewDoubleArray(JNIEnv* env, jsize length) {
1796 ScopedJniThreadState ts(env);
1797 return NewPrimitiveArray<jdoubleArray, DoubleArray>(ts, length);
1798 }
1799
1800 static jfloatArray NewFloatArray(JNIEnv* env, jsize length) {
1801 ScopedJniThreadState ts(env);
1802 return NewPrimitiveArray<jfloatArray, FloatArray>(ts, length);
1803 }
1804
1805 static jintArray NewIntArray(JNIEnv* env, jsize length) {
1806 ScopedJniThreadState ts(env);
1807 return NewPrimitiveArray<jintArray, IntArray>(ts, length);
1808 }
1809
1810 static jlongArray NewLongArray(JNIEnv* env, jsize length) {
1811 ScopedJniThreadState ts(env);
1812 return NewPrimitiveArray<jlongArray, LongArray>(ts, length);
1813 }
1814
1815 static jobjectArray NewObjectArray(JNIEnv* env, jsize length, jclass element_jclass, jobject initial_element) {
1816 ScopedJniThreadState ts(env);
1817 CHECK_GE(length, 0); // TODO: ReportJniError
1818
1819 // Compute the array class corresponding to the given element class.
1820 Class* element_class = Decode<Class*>(ts, element_jclass);
1821 std::string descriptor;
1822 descriptor += "[";
Brian Carlstrom9cff8e12011-08-18 16:47:29 -07001823 descriptor += element_class->GetDescriptor()->ToModifiedUtf8();
Elliott Hughescdf53122011-08-19 15:46:09 -07001824
1825 // Find the class.
1826 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
1827 // TODO: need to get the appropriate ClassLoader.
1828 Class* array_class = class_linker->FindClass(descriptor, NULL);
1829 if (array_class == NULL) {
1830 return NULL;
1831 }
1832
1833 ObjectArray<Object>* result = ObjectArray<Object>::Alloc(array_class, length);
1834 CHECK(initial_element == NULL); // TODO: support initial_element
1835 return AddLocalReference<jobjectArray>(ts, result);
1836 }
1837
1838 static jshortArray NewShortArray(JNIEnv* env, jsize length) {
1839 ScopedJniThreadState ts(env);
1840 return NewPrimitiveArray<jshortArray, ShortArray>(ts, length);
1841 }
1842
1843 static jboolean* GetBooleanArrayElements(JNIEnv* env,
1844 jbooleanArray array, jboolean* isCopy) {
1845 ScopedJniThreadState ts(env);
1846 UNIMPLEMENTED(FATAL);
1847 return NULL;
1848 }
1849
1850 static jbyte* GetByteArrayElements(JNIEnv* env, jbyteArray array, jboolean* isCopy) {
1851 ScopedJniThreadState ts(env);
1852 UNIMPLEMENTED(FATAL);
1853 return NULL;
1854 }
1855
1856 static jchar* GetCharArrayElements(JNIEnv* env, jcharArray array, jboolean* isCopy) {
1857 ScopedJniThreadState ts(env);
1858 UNIMPLEMENTED(FATAL);
1859 return NULL;
1860 }
1861
1862 static jshort* GetShortArrayElements(JNIEnv* env,
1863 jshortArray array, jboolean* isCopy) {
1864 ScopedJniThreadState ts(env);
1865 UNIMPLEMENTED(FATAL);
1866 return NULL;
1867 }
1868
1869 static jint* GetIntArrayElements(JNIEnv* env, jintArray array, jboolean* isCopy) {
1870 ScopedJniThreadState ts(env);
1871 UNIMPLEMENTED(FATAL);
1872 return NULL;
1873 }
1874
1875 static jlong* GetLongArrayElements(JNIEnv* env, jlongArray array, jboolean* isCopy) {
1876 ScopedJniThreadState ts(env);
1877 UNIMPLEMENTED(FATAL);
1878 return NULL;
1879 }
1880
1881 static jfloat* GetFloatArrayElements(JNIEnv* env,
1882 jfloatArray array, jboolean* isCopy) {
1883 ScopedJniThreadState ts(env);
1884 UNIMPLEMENTED(FATAL);
1885 return NULL;
1886 }
1887
1888 static jdouble* GetDoubleArrayElements(JNIEnv* env,
1889 jdoubleArray array, jboolean* isCopy) {
1890 ScopedJniThreadState ts(env);
1891 UNIMPLEMENTED(FATAL);
1892 return NULL;
1893 }
1894
1895 static void ReleaseBooleanArrayElements(JNIEnv* env,
1896 jbooleanArray array, jboolean* elems, jint mode) {
1897 ScopedJniThreadState ts(env);
1898 UNIMPLEMENTED(FATAL);
1899 }
1900
1901 static void ReleaseByteArrayElements(JNIEnv* env,
1902 jbyteArray array, jbyte* elems, jint mode) {
1903 ScopedJniThreadState ts(env);
1904 UNIMPLEMENTED(FATAL);
1905 }
1906
1907 static void ReleaseCharArrayElements(JNIEnv* env,
1908 jcharArray array, jchar* elems, jint mode) {
1909 ScopedJniThreadState ts(env);
1910 UNIMPLEMENTED(FATAL);
1911 }
1912
1913 static void ReleaseShortArrayElements(JNIEnv* env,
1914 jshortArray array, jshort* elems, jint mode) {
1915 ScopedJniThreadState ts(env);
1916 UNIMPLEMENTED(FATAL);
1917 }
1918
1919 static void ReleaseIntArrayElements(JNIEnv* env,
1920 jintArray array, jint* elems, jint mode) {
1921 ScopedJniThreadState ts(env);
1922 UNIMPLEMENTED(FATAL);
1923 }
1924
1925 static void ReleaseLongArrayElements(JNIEnv* env,
1926 jlongArray array, jlong* elems, jint mode) {
1927 ScopedJniThreadState ts(env);
1928 UNIMPLEMENTED(FATAL);
1929 }
1930
1931 static void ReleaseFloatArrayElements(JNIEnv* env,
1932 jfloatArray array, jfloat* elems, jint mode) {
1933 ScopedJniThreadState ts(env);
1934 UNIMPLEMENTED(FATAL);
1935 }
1936
1937 static void ReleaseDoubleArrayElements(JNIEnv* env,
1938 jdoubleArray array, jdouble* elems, jint mode) {
1939 ScopedJniThreadState ts(env);
1940 UNIMPLEMENTED(FATAL);
1941 }
1942
Elliott Hughes814e4032011-08-23 12:07:56 -07001943 static void GetBooleanArrayRegion(JNIEnv* env, jbooleanArray array, jsize start, jsize length, jboolean* buf) {
Elliott Hughescdf53122011-08-19 15:46:09 -07001944 ScopedJniThreadState ts(env);
Elliott Hughes814e4032011-08-23 12:07:56 -07001945 GetPrimitiveArrayRegion<jbooleanArray, jboolean, BooleanArray>(ts, array, start, length, buf);
Elliott Hughescdf53122011-08-19 15:46:09 -07001946 }
1947
Elliott Hughes814e4032011-08-23 12:07:56 -07001948 static void GetByteArrayRegion(JNIEnv* env, jbyteArray array, jsize start, jsize length, jbyte* buf) {
Elliott Hughescdf53122011-08-19 15:46:09 -07001949 ScopedJniThreadState ts(env);
Elliott Hughes814e4032011-08-23 12:07:56 -07001950 GetPrimitiveArrayRegion<jbyteArray, jbyte, ByteArray>(ts, array, start, length, buf);
Elliott Hughescdf53122011-08-19 15:46:09 -07001951 }
1952
Elliott Hughes814e4032011-08-23 12:07:56 -07001953 static void GetCharArrayRegion(JNIEnv* env, jcharArray array, jsize start, jsize length, jchar* buf) {
Elliott Hughescdf53122011-08-19 15:46:09 -07001954 ScopedJniThreadState ts(env);
Elliott Hughes814e4032011-08-23 12:07:56 -07001955 GetPrimitiveArrayRegion<jcharArray, jchar, CharArray>(ts, array, start, length, buf);
Elliott Hughescdf53122011-08-19 15:46:09 -07001956 }
1957
Elliott Hughes814e4032011-08-23 12:07:56 -07001958 static void GetDoubleArrayRegion(JNIEnv* env, jdoubleArray array, jsize start, jsize length, jdouble* buf) {
Elliott Hughescdf53122011-08-19 15:46:09 -07001959 ScopedJniThreadState ts(env);
Elliott Hughes814e4032011-08-23 12:07:56 -07001960 GetPrimitiveArrayRegion<jdoubleArray, jdouble, DoubleArray>(ts, array, start, length, buf);
Elliott Hughescdf53122011-08-19 15:46:09 -07001961 }
1962
Elliott Hughes814e4032011-08-23 12:07:56 -07001963 static void GetFloatArrayRegion(JNIEnv* env, jfloatArray array, jsize start, jsize length, jfloat* buf) {
Elliott Hughescdf53122011-08-19 15:46:09 -07001964 ScopedJniThreadState ts(env);
Elliott Hughes814e4032011-08-23 12:07:56 -07001965 GetPrimitiveArrayRegion<jfloatArray, jfloat, FloatArray>(ts, array, start, length, buf);
Elliott Hughescdf53122011-08-19 15:46:09 -07001966 }
1967
Elliott Hughes814e4032011-08-23 12:07:56 -07001968 static void GetIntArrayRegion(JNIEnv* env, jintArray array, jsize start, jsize length, jint* buf) {
Elliott Hughescdf53122011-08-19 15:46:09 -07001969 ScopedJniThreadState ts(env);
Elliott Hughes814e4032011-08-23 12:07:56 -07001970 GetPrimitiveArrayRegion<jintArray, jint, IntArray>(ts, array, start, length, buf);
Elliott Hughescdf53122011-08-19 15:46:09 -07001971 }
1972
Elliott Hughes814e4032011-08-23 12:07:56 -07001973 static void GetLongArrayRegion(JNIEnv* env, jlongArray array, jsize start, jsize length, jlong* buf) {
Elliott Hughescdf53122011-08-19 15:46:09 -07001974 ScopedJniThreadState ts(env);
Elliott Hughes814e4032011-08-23 12:07:56 -07001975 GetPrimitiveArrayRegion<jlongArray, jlong, LongArray>(ts, array, start, length, buf);
Elliott Hughescdf53122011-08-19 15:46:09 -07001976 }
1977
Elliott Hughes814e4032011-08-23 12:07:56 -07001978 static void GetShortArrayRegion(JNIEnv* env, jshortArray array, jsize start, jsize length, jshort* buf) {
Elliott Hughescdf53122011-08-19 15:46:09 -07001979 ScopedJniThreadState ts(env);
Elliott Hughes814e4032011-08-23 12:07:56 -07001980 GetPrimitiveArrayRegion<jshortArray, jshort, ShortArray>(ts, array, start, length, buf);
Elliott Hughescdf53122011-08-19 15:46:09 -07001981 }
1982
Elliott Hughes814e4032011-08-23 12:07:56 -07001983 static void SetBooleanArrayRegion(JNIEnv* env, jbooleanArray array, jsize start, jsize length, const jboolean* buf) {
Elliott Hughescdf53122011-08-19 15:46:09 -07001984 ScopedJniThreadState ts(env);
Elliott Hughes814e4032011-08-23 12:07:56 -07001985 SetPrimitiveArrayRegion<jbooleanArray, jboolean, BooleanArray>(ts, array, start, length, buf);
Elliott Hughescdf53122011-08-19 15:46:09 -07001986 }
1987
Elliott Hughes814e4032011-08-23 12:07:56 -07001988 static void SetByteArrayRegion(JNIEnv* env, jbyteArray array, jsize start, jsize length, const jbyte* buf) {
Elliott Hughescdf53122011-08-19 15:46:09 -07001989 ScopedJniThreadState ts(env);
Elliott Hughes814e4032011-08-23 12:07:56 -07001990 SetPrimitiveArrayRegion<jbyteArray, jbyte, ByteArray>(ts, array, start, length, buf);
Elliott Hughescdf53122011-08-19 15:46:09 -07001991 }
1992
Elliott Hughes814e4032011-08-23 12:07:56 -07001993 static void SetCharArrayRegion(JNIEnv* env, jcharArray array, jsize start, jsize length, const jchar* buf) {
Elliott Hughescdf53122011-08-19 15:46:09 -07001994 ScopedJniThreadState ts(env);
Elliott Hughes814e4032011-08-23 12:07:56 -07001995 SetPrimitiveArrayRegion<jcharArray, jchar, CharArray>(ts, array, start, length, buf);
Elliott Hughescdf53122011-08-19 15:46:09 -07001996 }
1997
Elliott Hughes814e4032011-08-23 12:07:56 -07001998 static void SetDoubleArrayRegion(JNIEnv* env, jdoubleArray array, jsize start, jsize length, const jdouble* buf) {
Elliott Hughescdf53122011-08-19 15:46:09 -07001999 ScopedJniThreadState ts(env);
Elliott Hughes814e4032011-08-23 12:07:56 -07002000 SetPrimitiveArrayRegion<jdoubleArray, jdouble, DoubleArray>(ts, array, start, length, buf);
Elliott Hughescdf53122011-08-19 15:46:09 -07002001 }
2002
Elliott Hughes814e4032011-08-23 12:07:56 -07002003 static void SetFloatArrayRegion(JNIEnv* env, jfloatArray array, jsize start, jsize length, const jfloat* buf) {
Elliott Hughescdf53122011-08-19 15:46:09 -07002004 ScopedJniThreadState ts(env);
Elliott Hughes814e4032011-08-23 12:07:56 -07002005 SetPrimitiveArrayRegion<jfloatArray, jfloat, FloatArray>(ts, array, start, length, buf);
Elliott Hughescdf53122011-08-19 15:46:09 -07002006 }
2007
Elliott Hughes814e4032011-08-23 12:07:56 -07002008 static void SetIntArrayRegion(JNIEnv* env, jintArray array, jsize start, jsize length, const jint* buf) {
Elliott Hughescdf53122011-08-19 15:46:09 -07002009 ScopedJniThreadState ts(env);
Elliott Hughes814e4032011-08-23 12:07:56 -07002010 SetPrimitiveArrayRegion<jintArray, jint, IntArray>(ts, array, start, length, buf);
Elliott Hughescdf53122011-08-19 15:46:09 -07002011 }
2012
Elliott Hughes814e4032011-08-23 12:07:56 -07002013 static void SetLongArrayRegion(JNIEnv* env, jlongArray array, jsize start, jsize length, const jlong* buf) {
Elliott Hughescdf53122011-08-19 15:46:09 -07002014 ScopedJniThreadState ts(env);
Elliott Hughes814e4032011-08-23 12:07:56 -07002015 SetPrimitiveArrayRegion<jlongArray, jlong, LongArray>(ts, array, start, length, buf);
Elliott Hughescdf53122011-08-19 15:46:09 -07002016 }
2017
Elliott Hughes814e4032011-08-23 12:07:56 -07002018 static void SetShortArrayRegion(JNIEnv* env, jshortArray array, jsize start, jsize length, const jshort* buf) {
Elliott Hughescdf53122011-08-19 15:46:09 -07002019 ScopedJniThreadState ts(env);
Elliott Hughes814e4032011-08-23 12:07:56 -07002020 SetPrimitiveArrayRegion<jshortArray, jshort, ShortArray>(ts, array, start, length, buf);
Elliott Hughescdf53122011-08-19 15:46:09 -07002021 }
2022
Elliott Hughes5174fe62011-08-23 15:12:35 -07002023 static jint RegisterNatives(JNIEnv* env, jclass java_class, const JNINativeMethod* methods, jint method_count) {
Elliott Hughescdf53122011-08-19 15:46:09 -07002024 ScopedJniThreadState ts(env);
Elliott Hughes5174fe62011-08-23 15:12:35 -07002025 Class* c = Decode<Class*>(ts, java_class);
2026
2027 JavaVMExt* vm = Runtime::Current()->GetJavaVM();
2028
2029 for (int i = 0; i < method_count; i++) {
Elliott Hughescdf53122011-08-19 15:46:09 -07002030 const char* name = methods[i].name;
2031 const char* sig = methods[i].signature;
2032
2033 if (*sig == '!') {
2034 // TODO: fast jni. it's too noisy to log all these.
2035 ++sig;
2036 }
2037
Elliott Hughes5174fe62011-08-23 15:12:35 -07002038 Method* m = c->FindDirectMethod(name, sig);
2039 if (m == NULL) {
2040 m = c->FindVirtualMethod(name, sig);
Elliott Hughescdf53122011-08-19 15:46:09 -07002041 }
Elliott Hughes5174fe62011-08-23 15:12:35 -07002042 if (m == NULL) {
Elliott Hughescdf53122011-08-19 15:46:09 -07002043 Thread* self = Thread::Current();
Elliott Hughes5174fe62011-08-23 15:12:35 -07002044 std::string class_descriptor(c->GetDescriptor()->ToModifiedUtf8());
Elliott Hughescdf53122011-08-19 15:46:09 -07002045 self->ThrowNewException("Ljava/lang/NoSuchMethodError;",
2046 "no method \"%s.%s%s\"",
Elliott Hughese5b0dc82011-08-23 09:59:02 -07002047 class_descriptor.c_str(), name, sig);
Elliott Hughescdf53122011-08-19 15:46:09 -07002048 return JNI_ERR;
Elliott Hughes5174fe62011-08-23 15:12:35 -07002049 } else if (!m->IsNative()) {
Elliott Hughescdf53122011-08-19 15:46:09 -07002050 Thread* self = Thread::Current();
Elliott Hughes5174fe62011-08-23 15:12:35 -07002051 std::string class_descriptor(c->GetDescriptor()->ToModifiedUtf8());
Elliott Hughescdf53122011-08-19 15:46:09 -07002052 self->ThrowNewException("Ljava/lang/NoSuchMethodError;",
2053 "method \"%s.%s%s\" is not native",
Elliott Hughese5b0dc82011-08-23 09:59:02 -07002054 class_descriptor.c_str(), name, sig);
Elliott Hughescdf53122011-08-19 15:46:09 -07002055 return JNI_ERR;
2056 }
Elliott Hughes5174fe62011-08-23 15:12:35 -07002057
2058 if (vm->verbose_jni) {
2059 LOG(INFO) << "[Registering JNI native method "
2060 << PrettyMethod(m, true) << "]";
2061 }
2062
2063 m->RegisterNative(methods[i].fnPtr);
Elliott Hughescdf53122011-08-19 15:46:09 -07002064 }
2065 return JNI_OK;
2066 }
2067
Elliott Hughes5174fe62011-08-23 15:12:35 -07002068 static jint UnregisterNatives(JNIEnv* env, jclass java_class) {
Elliott Hughescdf53122011-08-19 15:46:09 -07002069 ScopedJniThreadState ts(env);
Elliott Hughes5174fe62011-08-23 15:12:35 -07002070 Class* c = Decode<Class*>(ts, java_class);
2071
2072 JavaVMExt* vm = Runtime::Current()->GetJavaVM();
2073 if (vm->verbose_jni) {
2074 LOG(INFO) << "[Unregistering JNI native methods for "
2075 << PrettyDescriptor(c->GetDescriptor()) << "]";
2076 }
2077
2078 for (size_t i = 0; i < c->NumDirectMethods(); ++i) {
2079 Method* m = c->GetDirectMethod(i);
2080 if (m->IsNative()) {
2081 m->UnregisterNative();
2082 }
2083 }
2084 for (size_t i = 0; i < c->NumVirtualMethods(); ++i) {
2085 Method* m = c->GetVirtualMethod(i);
2086 if (m->IsNative()) {
2087 m->UnregisterNative();
2088 }
2089 }
2090
2091 return JNI_OK;
Elliott Hughescdf53122011-08-19 15:46:09 -07002092 }
2093
2094 static jint MonitorEnter(JNIEnv* env, jobject obj) {
2095 ScopedJniThreadState ts(env);
2096 UNIMPLEMENTED(WARNING);
2097 return 0;
2098 }
2099
2100 static jint MonitorExit(JNIEnv* env, jobject obj) {
2101 ScopedJniThreadState ts(env);
2102 UNIMPLEMENTED(WARNING);
2103 return 0;
2104 }
2105
2106 static jint GetJavaVM(JNIEnv* env, JavaVM** vm) {
2107 ScopedJniThreadState ts(env);
2108 Runtime* runtime = Runtime::Current();
2109 if (runtime != NULL) {
2110 *vm = reinterpret_cast<JavaVM*>(runtime->GetJavaVM());
2111 } else {
2112 *vm = NULL;
2113 }
2114 return (*vm != NULL) ? JNI_OK : JNI_ERR;
2115 }
2116
Elliott Hughescdf53122011-08-19 15:46:09 -07002117 static void* GetPrimitiveArrayCritical(JNIEnv* env,
2118 jarray array, jboolean* isCopy) {
2119 ScopedJniThreadState ts(env);
2120 UNIMPLEMENTED(FATAL);
2121 return NULL;
2122 }
2123
2124 static void ReleasePrimitiveArrayCritical(JNIEnv* env,
2125 jarray array, void* carray, jint mode) {
2126 ScopedJniThreadState ts(env);
2127 UNIMPLEMENTED(FATAL);
2128 }
2129
2130 static const jchar* GetStringCritical(JNIEnv* env, jstring s, jboolean* isCopy) {
2131 ScopedJniThreadState ts(env);
2132 UNIMPLEMENTED(FATAL);
2133 return NULL;
2134 }
2135
2136 static void ReleaseStringCritical(JNIEnv* env, jstring s, const jchar* cstr) {
2137 ScopedJniThreadState ts(env);
2138 UNIMPLEMENTED(FATAL);
2139 }
2140
Elliott Hughescdf53122011-08-19 15:46:09 -07002141 static jobject NewDirectByteBuffer(JNIEnv* env, void* address, jlong capacity) {
2142 ScopedJniThreadState ts(env);
2143 UNIMPLEMENTED(FATAL);
2144 return NULL;
2145 }
2146
2147 static void* GetDirectBufferAddress(JNIEnv* env, jobject buf) {
2148 ScopedJniThreadState ts(env);
2149 UNIMPLEMENTED(FATAL);
2150 return NULL;
2151 }
2152
2153 static jlong GetDirectBufferCapacity(JNIEnv* env, jobject buf) {
2154 ScopedJniThreadState ts(env);
2155 UNIMPLEMENTED(FATAL);
2156 return 0;
2157 }
2158
2159 static jobjectRefType GetObjectRefType(JNIEnv* env, jobject jobj) {
2160 ScopedJniThreadState ts(env);
2161 UNIMPLEMENTED(FATAL);
2162 return JNIInvalidRefType;
2163 }
2164};
Carl Shapiroea4dca82011-08-01 13:45:38 -07002165
Elliott Hughes40ef99e2011-08-11 17:44:34 -07002166static const struct JNINativeInterface gNativeInterface = {
Carl Shapiroea4dca82011-08-01 13:45:38 -07002167 NULL, // reserved0.
2168 NULL, // reserved1.
2169 NULL, // reserved2.
2170 NULL, // reserved3.
Elliott Hughescdf53122011-08-19 15:46:09 -07002171 JNI::GetVersion,
2172 JNI::DefineClass,
2173 JNI::FindClass,
2174 JNI::FromReflectedMethod,
2175 JNI::FromReflectedField,
2176 JNI::ToReflectedMethod,
2177 JNI::GetSuperclass,
2178 JNI::IsAssignableFrom,
2179 JNI::ToReflectedField,
2180 JNI::Throw,
2181 JNI::ThrowNew,
2182 JNI::ExceptionOccurred,
2183 JNI::ExceptionDescribe,
2184 JNI::ExceptionClear,
2185 JNI::FatalError,
2186 JNI::PushLocalFrame,
2187 JNI::PopLocalFrame,
2188 JNI::NewGlobalRef,
2189 JNI::DeleteGlobalRef,
2190 JNI::DeleteLocalRef,
2191 JNI::IsSameObject,
2192 JNI::NewLocalRef,
2193 JNI::EnsureLocalCapacity,
2194 JNI::AllocObject,
2195 JNI::NewObject,
2196 JNI::NewObjectV,
2197 JNI::NewObjectA,
2198 JNI::GetObjectClass,
2199 JNI::IsInstanceOf,
2200 JNI::GetMethodID,
2201 JNI::CallObjectMethod,
2202 JNI::CallObjectMethodV,
2203 JNI::CallObjectMethodA,
2204 JNI::CallBooleanMethod,
2205 JNI::CallBooleanMethodV,
2206 JNI::CallBooleanMethodA,
2207 JNI::CallByteMethod,
2208 JNI::CallByteMethodV,
2209 JNI::CallByteMethodA,
2210 JNI::CallCharMethod,
2211 JNI::CallCharMethodV,
2212 JNI::CallCharMethodA,
2213 JNI::CallShortMethod,
2214 JNI::CallShortMethodV,
2215 JNI::CallShortMethodA,
2216 JNI::CallIntMethod,
2217 JNI::CallIntMethodV,
2218 JNI::CallIntMethodA,
2219 JNI::CallLongMethod,
2220 JNI::CallLongMethodV,
2221 JNI::CallLongMethodA,
2222 JNI::CallFloatMethod,
2223 JNI::CallFloatMethodV,
2224 JNI::CallFloatMethodA,
2225 JNI::CallDoubleMethod,
2226 JNI::CallDoubleMethodV,
2227 JNI::CallDoubleMethodA,
2228 JNI::CallVoidMethod,
2229 JNI::CallVoidMethodV,
2230 JNI::CallVoidMethodA,
2231 JNI::CallNonvirtualObjectMethod,
2232 JNI::CallNonvirtualObjectMethodV,
2233 JNI::CallNonvirtualObjectMethodA,
2234 JNI::CallNonvirtualBooleanMethod,
2235 JNI::CallNonvirtualBooleanMethodV,
2236 JNI::CallNonvirtualBooleanMethodA,
2237 JNI::CallNonvirtualByteMethod,
2238 JNI::CallNonvirtualByteMethodV,
2239 JNI::CallNonvirtualByteMethodA,
2240 JNI::CallNonvirtualCharMethod,
2241 JNI::CallNonvirtualCharMethodV,
2242 JNI::CallNonvirtualCharMethodA,
2243 JNI::CallNonvirtualShortMethod,
2244 JNI::CallNonvirtualShortMethodV,
2245 JNI::CallNonvirtualShortMethodA,
2246 JNI::CallNonvirtualIntMethod,
2247 JNI::CallNonvirtualIntMethodV,
2248 JNI::CallNonvirtualIntMethodA,
2249 JNI::CallNonvirtualLongMethod,
2250 JNI::CallNonvirtualLongMethodV,
2251 JNI::CallNonvirtualLongMethodA,
2252 JNI::CallNonvirtualFloatMethod,
2253 JNI::CallNonvirtualFloatMethodV,
2254 JNI::CallNonvirtualFloatMethodA,
2255 JNI::CallNonvirtualDoubleMethod,
2256 JNI::CallNonvirtualDoubleMethodV,
2257 JNI::CallNonvirtualDoubleMethodA,
2258 JNI::CallNonvirtualVoidMethod,
2259 JNI::CallNonvirtualVoidMethodV,
2260 JNI::CallNonvirtualVoidMethodA,
2261 JNI::GetFieldID,
2262 JNI::GetObjectField,
2263 JNI::GetBooleanField,
2264 JNI::GetByteField,
2265 JNI::GetCharField,
2266 JNI::GetShortField,
2267 JNI::GetIntField,
2268 JNI::GetLongField,
2269 JNI::GetFloatField,
2270 JNI::GetDoubleField,
2271 JNI::SetObjectField,
2272 JNI::SetBooleanField,
2273 JNI::SetByteField,
2274 JNI::SetCharField,
2275 JNI::SetShortField,
2276 JNI::SetIntField,
2277 JNI::SetLongField,
2278 JNI::SetFloatField,
2279 JNI::SetDoubleField,
2280 JNI::GetStaticMethodID,
2281 JNI::CallStaticObjectMethod,
2282 JNI::CallStaticObjectMethodV,
2283 JNI::CallStaticObjectMethodA,
2284 JNI::CallStaticBooleanMethod,
2285 JNI::CallStaticBooleanMethodV,
2286 JNI::CallStaticBooleanMethodA,
2287 JNI::CallStaticByteMethod,
2288 JNI::CallStaticByteMethodV,
2289 JNI::CallStaticByteMethodA,
2290 JNI::CallStaticCharMethod,
2291 JNI::CallStaticCharMethodV,
2292 JNI::CallStaticCharMethodA,
2293 JNI::CallStaticShortMethod,
2294 JNI::CallStaticShortMethodV,
2295 JNI::CallStaticShortMethodA,
2296 JNI::CallStaticIntMethod,
2297 JNI::CallStaticIntMethodV,
2298 JNI::CallStaticIntMethodA,
2299 JNI::CallStaticLongMethod,
2300 JNI::CallStaticLongMethodV,
2301 JNI::CallStaticLongMethodA,
2302 JNI::CallStaticFloatMethod,
2303 JNI::CallStaticFloatMethodV,
2304 JNI::CallStaticFloatMethodA,
2305 JNI::CallStaticDoubleMethod,
2306 JNI::CallStaticDoubleMethodV,
2307 JNI::CallStaticDoubleMethodA,
2308 JNI::CallStaticVoidMethod,
2309 JNI::CallStaticVoidMethodV,
2310 JNI::CallStaticVoidMethodA,
2311 JNI::GetStaticFieldID,
2312 JNI::GetStaticObjectField,
2313 JNI::GetStaticBooleanField,
2314 JNI::GetStaticByteField,
2315 JNI::GetStaticCharField,
2316 JNI::GetStaticShortField,
2317 JNI::GetStaticIntField,
2318 JNI::GetStaticLongField,
2319 JNI::GetStaticFloatField,
2320 JNI::GetStaticDoubleField,
2321 JNI::SetStaticObjectField,
2322 JNI::SetStaticBooleanField,
2323 JNI::SetStaticByteField,
2324 JNI::SetStaticCharField,
2325 JNI::SetStaticShortField,
2326 JNI::SetStaticIntField,
2327 JNI::SetStaticLongField,
2328 JNI::SetStaticFloatField,
2329 JNI::SetStaticDoubleField,
2330 JNI::NewString,
2331 JNI::GetStringLength,
2332 JNI::GetStringChars,
2333 JNI::ReleaseStringChars,
2334 JNI::NewStringUTF,
2335 JNI::GetStringUTFLength,
2336 JNI::GetStringUTFChars,
2337 JNI::ReleaseStringUTFChars,
2338 JNI::GetArrayLength,
2339 JNI::NewObjectArray,
2340 JNI::GetObjectArrayElement,
2341 JNI::SetObjectArrayElement,
2342 JNI::NewBooleanArray,
2343 JNI::NewByteArray,
2344 JNI::NewCharArray,
2345 JNI::NewShortArray,
2346 JNI::NewIntArray,
2347 JNI::NewLongArray,
2348 JNI::NewFloatArray,
2349 JNI::NewDoubleArray,
2350 JNI::GetBooleanArrayElements,
2351 JNI::GetByteArrayElements,
2352 JNI::GetCharArrayElements,
2353 JNI::GetShortArrayElements,
2354 JNI::GetIntArrayElements,
2355 JNI::GetLongArrayElements,
2356 JNI::GetFloatArrayElements,
2357 JNI::GetDoubleArrayElements,
2358 JNI::ReleaseBooleanArrayElements,
2359 JNI::ReleaseByteArrayElements,
2360 JNI::ReleaseCharArrayElements,
2361 JNI::ReleaseShortArrayElements,
2362 JNI::ReleaseIntArrayElements,
2363 JNI::ReleaseLongArrayElements,
2364 JNI::ReleaseFloatArrayElements,
2365 JNI::ReleaseDoubleArrayElements,
2366 JNI::GetBooleanArrayRegion,
2367 JNI::GetByteArrayRegion,
2368 JNI::GetCharArrayRegion,
2369 JNI::GetShortArrayRegion,
2370 JNI::GetIntArrayRegion,
2371 JNI::GetLongArrayRegion,
2372 JNI::GetFloatArrayRegion,
2373 JNI::GetDoubleArrayRegion,
2374 JNI::SetBooleanArrayRegion,
2375 JNI::SetByteArrayRegion,
2376 JNI::SetCharArrayRegion,
2377 JNI::SetShortArrayRegion,
2378 JNI::SetIntArrayRegion,
2379 JNI::SetLongArrayRegion,
2380 JNI::SetFloatArrayRegion,
2381 JNI::SetDoubleArrayRegion,
2382 JNI::RegisterNatives,
2383 JNI::UnregisterNatives,
2384 JNI::MonitorEnter,
2385 JNI::MonitorExit,
2386 JNI::GetJavaVM,
2387 JNI::GetStringRegion,
2388 JNI::GetStringUTFRegion,
2389 JNI::GetPrimitiveArrayCritical,
2390 JNI::ReleasePrimitiveArrayCritical,
2391 JNI::GetStringCritical,
2392 JNI::ReleaseStringCritical,
2393 JNI::NewWeakGlobalRef,
2394 JNI::DeleteWeakGlobalRef,
2395 JNI::ExceptionCheck,
2396 JNI::NewDirectByteBuffer,
2397 JNI::GetDirectBufferAddress,
2398 JNI::GetDirectBufferCapacity,
2399 JNI::GetObjectRefType,
Carl Shapiroea4dca82011-08-01 13:45:38 -07002400};
2401
Elliott Hughes6c1a3942011-08-17 15:00:06 -07002402static const size_t kMonitorsInitial = 32; // Arbitrary.
2403static const size_t kMonitorsMax = 4096; // Arbitrary sanity check.
2404
2405static const size_t kLocalsInitial = 64; // Arbitrary.
2406static const size_t kLocalsMax = 512; // Arbitrary sanity check.
Elliott Hughesbbd76712011-08-17 10:25:24 -07002407
Elliott Hughes515a5bc2011-08-17 11:08:34 -07002408JNIEnvExt::JNIEnvExt(Thread* self, bool check_jni)
Elliott Hughesbbd76712011-08-17 10:25:24 -07002409 : fns(&gNativeInterface),
2410 self(self),
Elliott Hughes515a5bc2011-08-17 11:08:34 -07002411 check_jni(check_jni),
Elliott Hughesbbd76712011-08-17 10:25:24 -07002412 critical(false),
Elliott Hughes6c1a3942011-08-17 15:00:06 -07002413 monitors("monitors", kMonitorsInitial, kMonitorsMax),
2414 locals(kLocalsInitial, kLocalsMax, kLocal) {
Elliott Hughes40ef99e2011-08-11 17:44:34 -07002415}
2416
Carl Shapiroea4dca82011-08-01 13:45:38 -07002417// JNI Invocation interface.
2418
Carl Shapiro2ed144c2011-07-26 16:52:08 -07002419extern "C" jint JNI_CreateJavaVM(JavaVM** p_vm, void** p_env, void* vm_args) {
2420 const JavaVMInitArgs* args = static_cast<JavaVMInitArgs*>(vm_args);
2421 if (args->version < JNI_VERSION_1_2) {
2422 return JNI_EVERSION;
2423 }
2424 Runtime::Options options;
2425 for (int i = 0; i < args->nOptions; ++i) {
2426 JavaVMOption* option = &args->options[i];
Carl Shapirofc322c72011-07-27 00:20:01 -07002427 options.push_back(std::make_pair(StringPiece(option->optionString),
2428 option->extraInfo));
Carl Shapiro2ed144c2011-07-26 16:52:08 -07002429 }
2430 bool ignore_unrecognized = args->ignoreUnrecognized;
Elliott Hughesf2682d52011-08-15 16:37:04 -07002431 Runtime* runtime = Runtime::Create(options, ignore_unrecognized);
Carl Shapiro2ed144c2011-07-26 16:52:08 -07002432 if (runtime == NULL) {
2433 return JNI_ERR;
2434 } else {
2435 *p_env = reinterpret_cast<JNIEnv*>(Thread::Current()->GetJniEnv());
Elliott Hughes0af55432011-08-17 18:37:28 -07002436 *p_vm = reinterpret_cast<JavaVM*>(runtime->GetJavaVM());
Carl Shapiro2ed144c2011-07-26 16:52:08 -07002437 return JNI_OK;
2438 }
2439}
2440
Elliott Hughesf2682d52011-08-15 16:37:04 -07002441extern "C" jint JNI_GetCreatedJavaVMs(JavaVM** vms, jsize, jsize* vm_count) {
Carl Shapiro2ed144c2011-07-26 16:52:08 -07002442 Runtime* runtime = Runtime::Current();
2443 if (runtime == NULL) {
Elliott Hughesf2682d52011-08-15 16:37:04 -07002444 *vm_count = 0;
Carl Shapiro2ed144c2011-07-26 16:52:08 -07002445 } else {
Elliott Hughesf2682d52011-08-15 16:37:04 -07002446 *vm_count = 1;
Elliott Hughes0af55432011-08-17 18:37:28 -07002447 vms[0] = reinterpret_cast<JavaVM*>(runtime->GetJavaVM());
Carl Shapiro2ed144c2011-07-26 16:52:08 -07002448 }
2449 return JNI_OK;
2450}
2451
2452// Historically unsupported.
2453extern "C" jint JNI_GetDefaultJavaVMInitArgs(void* vm_args) {
2454 return JNI_ERR;
2455}
2456
Elliott Hughescdf53122011-08-19 15:46:09 -07002457class JII {
2458 public:
2459 static jint DestroyJavaVM(JavaVM* vm) {
2460 if (vm == NULL) {
2461 return JNI_ERR;
2462 } else {
2463 JavaVMExt* raw_vm = reinterpret_cast<JavaVMExt*>(vm);
2464 delete raw_vm->runtime;
2465 return JNI_OK;
2466 }
Carl Shapiro2ed144c2011-07-26 16:52:08 -07002467 }
Carl Shapiro2ed144c2011-07-26 16:52:08 -07002468
Elliott Hughescdf53122011-08-19 15:46:09 -07002469 static jint AttachCurrentThread(JavaVM* vm, JNIEnv** p_env, void* thr_args) {
2470 if (vm == NULL || p_env == NULL) {
2471 return JNI_ERR;
2472 }
Elliott Hughesf2682d52011-08-15 16:37:04 -07002473 JavaVMExt* raw_vm = reinterpret_cast<JavaVMExt*>(vm);
2474 Runtime* runtime = raw_vm->runtime;
Elliott Hughescdf53122011-08-19 15:46:09 -07002475 const char* name = NULL;
2476 if (thr_args != NULL) {
2477 // TODO: check version
2478 name = static_cast<JavaVMAttachArgs*>(thr_args)->name;
2479 // TODO: thread group
2480 }
2481 bool success = runtime->AttachCurrentThread(name, p_env);
2482 if (!success) {
2483 return JNI_ERR;
2484 } else {
2485 return JNI_OK;
2486 }
2487 }
2488
2489 static jint AttachCurrentThreadAsDaemon(JavaVM* vm, JNIEnv** p_env, void* thr_args) {
2490 if (vm == NULL || p_env == NULL) {
2491 return JNI_ERR;
2492 }
2493 JavaVMExt* raw_vm = reinterpret_cast<JavaVMExt*>(vm);
2494 Runtime* runtime = raw_vm->runtime;
2495 const char* name = NULL;
2496 if (thr_args != NULL) {
2497 // TODO: check version
2498 name = static_cast<JavaVMAttachArgs*>(thr_args)->name;
2499 // TODO: thread group
2500 }
2501 bool success = runtime->AttachCurrentThreadAsDaemon(name, p_env);
2502 if (!success) {
2503 return JNI_ERR;
2504 } else {
2505 return JNI_OK;
2506 }
2507 }
2508
2509 static jint DetachCurrentThread(JavaVM* vm) {
2510 if (vm == NULL) {
2511 return JNI_ERR;
2512 } else {
2513 JavaVMExt* raw_vm = reinterpret_cast<JavaVMExt*>(vm);
2514 Runtime* runtime = raw_vm->runtime;
2515 runtime->DetachCurrentThread();
2516 return JNI_OK;
2517 }
2518 }
2519
2520 static jint GetEnv(JavaVM* vm, void** env, jint version) {
2521 if (version < JNI_VERSION_1_1 || version > JNI_VERSION_1_6) {
2522 return JNI_EVERSION;
2523 }
2524 if (vm == NULL || env == NULL) {
2525 return JNI_ERR;
2526 }
2527 Thread* thread = Thread::Current();
2528 if (thread == NULL) {
2529 *env = NULL;
2530 return JNI_EDETACHED;
2531 }
2532 *env = thread->GetJniEnv();
Carl Shapiro2ed144c2011-07-26 16:52:08 -07002533 return JNI_OK;
2534 }
Elliott Hughescdf53122011-08-19 15:46:09 -07002535};
Carl Shapiro2ed144c2011-07-26 16:52:08 -07002536
Elliott Hughesf2682d52011-08-15 16:37:04 -07002537struct JNIInvokeInterface gInvokeInterface = {
Carl Shapiroea4dca82011-08-01 13:45:38 -07002538 NULL, // reserved0
2539 NULL, // reserved1
2540 NULL, // reserved2
Elliott Hughescdf53122011-08-19 15:46:09 -07002541 JII::DestroyJavaVM,
2542 JII::AttachCurrentThread,
2543 JII::DetachCurrentThread,
2544 JII::GetEnv,
2545 JII::AttachCurrentThreadAsDaemon
Carl Shapiroea4dca82011-08-01 13:45:38 -07002546};
2547
Elliott Hughesbbd76712011-08-17 10:25:24 -07002548static const size_t kPinTableInitialSize = 16;
2549static const size_t kPinTableMaxSize = 1024;
2550
Elliott Hughes6c1a3942011-08-17 15:00:06 -07002551static const size_t kGlobalsInitial = 512; // Arbitrary.
2552static const size_t kGlobalsMax = 51200; // Arbitrary sanity check.
2553
2554static const size_t kWeakGlobalsInitial = 16; // Arbitrary.
2555static const size_t kWeakGlobalsMax = 51200; // Arbitrary sanity check.
2556
Elliott Hughes0af55432011-08-17 18:37:28 -07002557JavaVMExt::JavaVMExt(Runtime* runtime, bool check_jni, bool verbose_jni)
Elliott Hughesbbd76712011-08-17 10:25:24 -07002558 : fns(&gInvokeInterface),
2559 runtime(runtime),
Elliott Hughes515a5bc2011-08-17 11:08:34 -07002560 check_jni(check_jni),
Elliott Hughes0af55432011-08-17 18:37:28 -07002561 verbose_jni(verbose_jni),
Elliott Hughes6c1a3942011-08-17 15:00:06 -07002562 pin_table("pin table", kPinTableInitialSize, kPinTableMaxSize),
Elliott Hughes18c07532011-08-18 15:50:51 -07002563 globals_lock(Mutex::Create("JNI global reference table lock")),
Elliott Hughes6c1a3942011-08-17 15:00:06 -07002564 globals(kGlobalsInitial, kGlobalsMax, kGlobal),
Elliott Hughes18c07532011-08-18 15:50:51 -07002565 weak_globals_lock(Mutex::Create("JNI weak global reference table lock")),
Elliott Hughes6c1a3942011-08-17 15:00:06 -07002566 weak_globals(kWeakGlobalsInitial, kWeakGlobalsMax, kWeakGlobal) {
Elliott Hughesf2682d52011-08-15 16:37:04 -07002567}
2568
Elliott Hughesde69d7f2011-08-18 16:49:37 -07002569JavaVMExt::~JavaVMExt() {
2570 delete globals_lock;
2571 delete weak_globals_lock;
2572}
2573
Elliott Hughescdf53122011-08-19 15:46:09 -07002574/*
2575 * Load native code from the specified absolute pathname. Per the spec,
2576 * if we've already loaded a library with the specified pathname, we
2577 * return without doing anything.
2578 *
2579 * TODO? for better results we should absolutify the pathname. For fully
2580 * correct results we should stat to get the inode and compare that. The
2581 * existing implementation is fine so long as everybody is using
2582 * System.loadLibrary.
2583 *
2584 * The library will be associated with the specified class loader. The JNI
2585 * spec says we can't load the same library into more than one class loader.
2586 *
2587 * Returns "true" on success. On failure, sets *detail to a
2588 * human-readable description of the error or NULL if no detail is
2589 * available; ownership of the string is transferred to the caller.
2590 */
Elliott Hughes814e4032011-08-23 12:07:56 -07002591bool JavaVMExt::LoadNativeLibrary(const std::string& path, ClassLoader* class_loader, char** detail) {
Elliott Hughescdf53122011-08-19 15:46:09 -07002592 *detail = NULL;
2593
2594 // See if we've already loaded this library. If we have, and the class loader
2595 // matches, return successfully without doing anything.
2596 SharedLibrary* library = libraries[path];
2597 if (library != NULL) {
2598 if (library->GetClassLoader() != class_loader) {
2599 LOG(WARNING) << "Shared library \"" << path << "\" already opened by "
2600 << "ClassLoader " << library->GetClassLoader() << "; "
2601 << "can't open in " << class_loader;
2602 *detail = strdup("already opened by different ClassLoader");
2603 return false;
2604 }
2605 if (verbose_jni) {
2606 LOG(INFO) << "[Shared library \"" << path << "\" already loaded in "
2607 << "ClassLoader " << class_loader << "]";
2608 }
2609 if (!library->CheckOnLoadResult(this)) {
2610 *detail = strdup("JNI_OnLoad failed before");
2611 return false;
2612 }
2613 return true;
2614 }
2615
2616 // Open the shared library. Because we're using a full path, the system
2617 // doesn't have to search through LD_LIBRARY_PATH. (It may do so to
2618 // resolve this library's dependencies though.)
2619
2620 // Failures here are expected when java.library.path has several entries
2621 // and we have to hunt for the lib.
2622
2623 // The current version of the dynamic linker prints detailed information
2624 // about dlopen() failures. Some things to check if the message is
2625 // cryptic:
2626 // - make sure the library exists on the device
2627 // - verify that the right path is being opened (the debug log message
2628 // above can help with that)
2629 // - check to see if the library is valid (e.g. not zero bytes long)
2630 // - check config/prelink-linux-arm.map to ensure that the library
2631 // is listed and is not being overrun by the previous entry (if
2632 // loading suddenly stops working on a prelinked library, this is
2633 // a good one to check)
2634 // - write a trivial app that calls sleep() then dlopen(), attach
2635 // to it with "strace -p <pid>" while it sleeps, and watch for
2636 // attempts to open nonexistent dependent shared libs
2637
2638 // TODO: automate some of these checks!
2639
2640 // This can execute slowly for a large library on a busy system, so we
2641 // want to switch from RUNNING to VMWAIT while it executes. This allows
2642 // the GC to ignore us.
2643 Thread* self = Thread::Current();
2644 Thread::State old_state = self->GetState();
2645 self->SetState(Thread::kWaiting); // TODO: VMWAIT
2646 void* handle = dlopen(path.c_str(), RTLD_LAZY);
2647 self->SetState(old_state);
2648
2649 if (verbose_jni) {
2650 LOG(INFO) << "[Call to dlopen(\"" << path << "\") returned " << handle << "]";
2651 }
2652
2653 if (handle == NULL) {
2654 *detail = strdup(dlerror());
2655 return false;
2656 }
2657
2658 // Create a new entry.
2659 library = new SharedLibrary(path, handle, class_loader);
Elliott Hughescdf53122011-08-19 15:46:09 -07002660
2661 libraries[path] = library;
2662
2663 // if (pNewEntry != pActualEntry) {
2664 // LOG(INFO) << "WOW: we lost a race to add a shared library (\"" << path << "\" ClassLoader=" << class_loader <<")";
2665 // freeSharedLibEntry(pNewEntry);
2666 // return CheckOnLoadResult(this, pActualEntry);
2667 // } else
2668 {
2669 if (verbose_jni) {
2670 LOG(INFO) << "[Added shared library \"" << path << "\" for ClassLoader " << class_loader << "]";
2671 }
2672
2673 bool result = true;
2674 void* sym = dlsym(handle, "JNI_OnLoad");
2675 if (sym == NULL) {
2676 if (verbose_jni) {
2677 LOG(INFO) << "[No JNI_OnLoad found in \"" << path << "\"]";
2678 }
2679 } else {
2680 // Call JNI_OnLoad. We have to override the current class
2681 // loader, which will always be "null" since the stuff at the
2682 // top of the stack is around Runtime.loadLibrary(). (See
2683 // the comments in the JNI FindClass function.)
Elliott Hughescdf53122011-08-19 15:46:09 -07002684 typedef int (*JNI_OnLoadFn)(JavaVM*, void*);
2685 JNI_OnLoadFn jni_on_load = reinterpret_cast<JNI_OnLoadFn>(sym);
Elliott Hughes814e4032011-08-23 12:07:56 -07002686 ClassLoader* old_class_loader = self->GetClassLoaderOverride();
2687 self->SetClassLoaderOverride(class_loader);
Elliott Hughescdf53122011-08-19 15:46:09 -07002688
2689 old_state = self->GetState();
2690 self->SetState(Thread::kNative);
2691 if (verbose_jni) {
2692 LOG(INFO) << "[Calling JNI_OnLoad in \"" << path << "\"]";
2693 }
2694 int version = (*jni_on_load)(reinterpret_cast<JavaVM*>(this), NULL);
2695 self->SetState(old_state);
2696
Elliott Hughes814e4032011-08-23 12:07:56 -07002697 self->SetClassLoaderOverride(old_class_loader);;
Elliott Hughescdf53122011-08-19 15:46:09 -07002698
2699 if (version != JNI_VERSION_1_2 &&
2700 version != JNI_VERSION_1_4 &&
2701 version != JNI_VERSION_1_6) {
2702 LOG(WARNING) << "JNI_OnLoad in \"" << path << "\" returned "
2703 << "bad version: " << version;
2704 // It's unwise to call dlclose() here, but we can mark it
2705 // as bad and ensure that future load attempts will fail.
2706 // We don't know how far JNI_OnLoad got, so there could
2707 // be some partially-initialized stuff accessible through
2708 // newly-registered native method calls. We could try to
2709 // unregister them, but that doesn't seem worthwhile.
2710 result = false;
2711 } else {
2712 if (verbose_jni) {
2713 LOG(INFO) << "[Returned " << (result ? "successfully" : "failure")
2714 << " from JNI_OnLoad in \"" << path << "\"]";
2715 }
2716 }
2717 }
2718
2719 library->SetResult(result);
2720 return result;
2721 }
2722}
2723
Ian Rogersdf20fe02011-07-20 20:34:16 -07002724} // namespace art