blob: 79986c2afd391af7a898db398a6f1b97ef40d599 [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 Hughes18c07532011-08-18 15:50:51 -070060 }
61
62 ~SharedLibrary() {
Elliott Hughescdf53122011-08-19 15:46:09 -070063 delete jni_on_load_lock_;
Elliott Hughes0af55432011-08-17 18:37:28 -070064 }
65
Elliott Hughescdf53122011-08-19 15:46:09 -070066 Object* GetClassLoader() {
67 return class_loader_;
Elliott Hughes0af55432011-08-17 18:37:28 -070068 }
69
Elliott Hughescdf53122011-08-19 15:46:09 -070070 /*
71 * Check the result of an earlier call to JNI_OnLoad on this library. If
72 * the call has not yet finished in another thread, wait for it.
73 */
74 bool CheckOnLoadResult(JavaVMExt* vm) {
75 Thread* self = Thread::Current();
76 if (jni_on_load_tid_ == self->GetId()) {
77 // Check this so we don't end up waiting for ourselves. We need
78 // to return "true" so the caller can continue.
79 LOG(INFO) << *self << " recursive attempt to load library "
80 << "\"" << path_ << "\"";
81 return true;
Elliott Hughes0af55432011-08-17 18:37:28 -070082 }
83
Elliott Hughescdf53122011-08-19 15:46:09 -070084 UNIMPLEMENTED(ERROR) << "need to pthread_cond_wait!";
85 // MutexLock mu(jni_on_load_lock_);
86 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
93 // pthread_cond_wait(&jni_on_load_cond_, &jni_on_load_lock_);
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.
110 UNIMPLEMENTED(ERROR) << "missing pthread_cond_broadcast";
Elliott Hughescdf53122011-08-19 15:46:09 -0700111 // MutexLock mu(library->jni_on_load_lock_);
112 // pthread_cond_broadcast(&library->jni_on_load_cond_);
Elliott Hughes0af55432011-08-17 18:37:28 -0700113 }
Elliott Hughescdf53122011-08-19 15:46:09 -0700114
115 private:
116 enum JNI_OnLoadState {
117 kPending,
118 kFailed,
119 kOkay,
120 };
121
122 // Path to library "/system/lib/libjni.so".
123 std::string path_;
124
125 // The void* returned by dlopen(3).
126 void* handle_;
127
128 // The ClassLoader this library is associated with.
129 Object* class_loader_;
130
131 // Guards remaining items.
132 Mutex* jni_on_load_lock_;
133 // Wait for JNI_OnLoad in other thread.
134 pthread_cond_t jni_on_load_cond_;
135 // Recursive invocation guard.
136 uint32_t jni_on_load_tid_;
137 // Result of earlier JNI_OnLoad call.
138 JNI_OnLoadState jni_on_load_result_;
139};
140
141namespace {
Elliott Hughes0af55432011-08-17 18:37:28 -0700142
Elliott Hughes22f40932011-08-12 13:06:37 -0700143// Entry/exit processing for all JNI calls.
144//
145// This performs the necessary thread state switching, lets us amortize the
146// cost of working out the current thread, and lets us check (and repair) apps
147// that are using a JNIEnv on the wrong thread.
148class ScopedJniThreadState {
149 public:
Elliott Hughesc5f7c912011-08-18 14:00:42 -0700150 explicit ScopedJniThreadState(JNIEnv* env)
151 : env_(reinterpret_cast<JNIEnvExt*>(env)) {
Elliott Hughesb20a5542011-08-12 18:03:12 -0700152 self_ = ThreadForEnv(env);
Elliott Hughes22f40932011-08-12 13:06:37 -0700153 self_->SetState(Thread::kRunnable);
154 }
155
156 ~ScopedJniThreadState() {
157 self_->SetState(Thread::kNative);
158 }
159
Elliott Hughesc5f7c912011-08-18 14:00:42 -0700160 JNIEnvExt* Env() {
161 return env_;
162 }
163
Elliott Hughesb20a5542011-08-12 18:03:12 -0700164 Thread* Self() {
Elliott Hughes22f40932011-08-12 13:06:37 -0700165 return self_;
166 }
167
Elliott Hughesb20a5542011-08-12 18:03:12 -0700168 private:
169 static Thread* ThreadForEnv(JNIEnv* env) {
Elliott Hughes22f40932011-08-12 13:06:37 -0700170 // TODO: need replacement for gDvmJni.
171 bool workAroundAppJniBugs = true;
172 Thread* env_self = reinterpret_cast<JNIEnvExt*>(env)->self;
173 Thread* self = workAroundAppJniBugs ? Thread::Current() : env_self;
174 if (self != env_self) {
Elliott Hughes330304d2011-08-12 14:28:05 -0700175 LOG(ERROR) << "JNI ERROR: JNIEnv for " << *env_self
176 << " used on " << *self;
177 // TODO: dump stack
Elliott Hughes22f40932011-08-12 13:06:37 -0700178 }
179 return self;
180 }
181
Elliott Hughesc5f7c912011-08-18 14:00:42 -0700182 JNIEnvExt* env_;
Elliott Hughes22f40932011-08-12 13:06:37 -0700183 Thread* self_;
184 DISALLOW_COPY_AND_ASSIGN(ScopedJniThreadState);
185};
186
Elliott Hughesc5f7c912011-08-18 14:00:42 -0700187/*
188 * Add a local reference for an object to the current stack frame. When
189 * the native function returns, the reference will be discarded.
190 *
191 * We need to allow the same reference to be added multiple times.
192 *
193 * This will be called on otherwise unreferenced objects. We cannot do
194 * GC allocations here, and it's best if we don't grab a mutex.
195 *
196 * Returns the local reference (currently just the same pointer that was
197 * passed in), or NULL on failure.
198 */
Elliott Hughes8a26c5c2011-08-15 18:35:43 -0700199template<typename T>
200T AddLocalReference(ScopedJniThreadState& ts, Object* obj) {
Elliott Hughesc5f7c912011-08-18 14:00:42 -0700201 if (obj == NULL) {
202 return NULL;
203 }
204
205 IndirectReferenceTable& locals = ts.Env()->locals;
206
207 uint32_t cookie = IRT_FIRST_SEGMENT; // TODO
208 IndirectRef ref = locals.Add(cookie, obj);
209 if (ref == NULL) {
210 // TODO: just change Add's DCHECK to CHECK and lose this?
211 locals.Dump();
212 LOG(FATAL) << "Failed adding to JNI local reference table "
213 << "(has " << locals.Capacity() << " entries)";
214 // TODO: dvmDumpThread(dvmThreadSelf(), false);
215 }
216
217#if 0 // TODO: fix this to understand PushLocalFrame, so we can turn it on.
218 if (ts.Env()->check_jni) {
219 size_t entry_count = locals.Capacity();
220 if (entry_count > 16) {
Elliott Hughese5b0dc82011-08-23 09:59:02 -0700221 std::string class_descriptor(PrettyDescriptor(obj->GetClass()->GetDescriptor()));
Elliott Hughesc5f7c912011-08-18 14:00:42 -0700222 LOG(WARNING) << "Warning: more than 16 JNI local references: "
Elliott Hughese5b0dc82011-08-23 09:59:02 -0700223 << entry_count << " (most recent was a " << class_descriptor << ")";
Elliott Hughesc5f7c912011-08-18 14:00:42 -0700224 locals.Dump();
225 // TODO: dvmDumpThread(dvmThreadSelf(), false);
226 // dvmAbort();
227 }
228 }
229#endif
230
231 if (false /*gDvmJni.workAroundAppJniBugs*/) { // TODO
232 // Hand out direct pointers to support broken old apps.
233 return reinterpret_cast<T>(obj);
234 }
235
236 return reinterpret_cast<T>(ref);
237}
238
Elliott Hughescdf53122011-08-19 15:46:09 -0700239jweak AddWeakGlobalReference(ScopedJniThreadState& ts, Object* obj) {
240 if (obj == NULL) {
241 return NULL;
242 }
243 JavaVMExt* vm = Runtime::Current()->GetJavaVM();
244 IndirectReferenceTable& weak_globals = vm->weak_globals;
245 MutexLock mu(vm->weak_globals_lock);
246 IndirectRef ref = weak_globals.Add(IRT_FIRST_SEGMENT, obj);
247 return reinterpret_cast<jweak>(ref);
248}
249
Elliott Hughesc5f7c912011-08-18 14:00:42 -0700250template<typename T>
251T Decode(ScopedJniThreadState& ts, jobject obj) {
252 if (obj == NULL) {
253 return NULL;
254 }
255
256 IndirectRef ref = reinterpret_cast<IndirectRef>(obj);
257 IndirectRefKind kind = GetIndirectRefKind(ref);
258 Object* result;
259 switch (kind) {
260 case kLocal:
261 {
262 IndirectReferenceTable& locals = ts.Env()->locals;
263 result = locals.Get(ref);
264 break;
265 }
266 case kGlobal:
267 {
268 JavaVMExt* vm = Runtime::Current()->GetJavaVM();
269 IndirectReferenceTable& globals = vm->globals;
Elliott Hughes18c07532011-08-18 15:50:51 -0700270 MutexLock mu(vm->globals_lock);
Elliott Hughesc5f7c912011-08-18 14:00:42 -0700271 result = globals.Get(ref);
272 break;
273 }
274 case kWeakGlobal:
275 {
276 JavaVMExt* vm = Runtime::Current()->GetJavaVM();
277 IndirectReferenceTable& weak_globals = vm->weak_globals;
Elliott Hughes18c07532011-08-18 15:50:51 -0700278 MutexLock mu(vm->weak_globals_lock);
Elliott Hughesc5f7c912011-08-18 14:00:42 -0700279 result = weak_globals.Get(ref);
280 if (result == kClearedJniWeakGlobal) {
281 // This is a special case where it's okay to return NULL.
282 return NULL;
283 }
284 break;
285 }
286 case kInvalid:
287 default:
Ian Rogersa8cd9f42011-08-19 16:43:41 -0700288 // TODO: make stack handle blocks more efficient
289 // Check if this is a local reference in a stack handle block
290 if (ts.Self()->ShbContains(obj)) {
291 return *reinterpret_cast<T*>(obj); // Read from stack handle block
292 }
Elliott Hughesc5f7c912011-08-18 14:00:42 -0700293 if (false /*gDvmJni.workAroundAppJniBugs*/) { // TODO
294 // Assume an invalid local reference is actually a direct pointer.
295 return reinterpret_cast<T>(obj);
296 }
297 LOG(FATAL) << "Invalid indirect reference " << obj;
298 return reinterpret_cast<T>(kInvalidIndirectRefObject);
299 }
300
301 if (result == NULL) {
302 LOG(FATAL) << "JNI ERROR (app bug): use of deleted " << kind << ": "
303 << obj;
304 }
305 return reinterpret_cast<T>(result);
Elliott Hughes8a26c5c2011-08-15 18:35:43 -0700306}
307
Elliott Hughescdf53122011-08-19 15:46:09 -0700308Field* DecodeField(ScopedJniThreadState& ts, jfieldID fid) {
309 return Decode<Field*>(ts, reinterpret_cast<jweak>(fid));
310}
Carl Shapiro9b9ba282011-08-14 15:30:39 -0700311
Elliott Hughescdf53122011-08-19 15:46:09 -0700312Method* DecodeMethod(ScopedJniThreadState& ts, jmethodID mid) {
313 return Decode<Method*>(ts, reinterpret_cast<jweak>(mid));
Carl Shapiro9b9ba282011-08-14 15:30:39 -0700314}
315
Elliott Hughesc5f7c912011-08-18 14:00:42 -0700316byte* CreateArgArray(ScopedJniThreadState& ts, Method* method, va_list ap) {
Carl Shapiro9b9ba282011-08-14 15:30:39 -0700317 size_t num_bytes = method->NumArgArrayBytes();
318 scoped_array<byte> arg_array(new byte[num_bytes]);
319 const StringPiece& shorty = method->GetShorty();
Ian Rogers4dd71f12011-08-16 14:16:02 -0700320 for (int i = 1, offset = 0; i < shorty.size(); ++i) {
Carl Shapiro9b9ba282011-08-14 15:30:39 -0700321 switch (shorty[i]) {
322 case 'Z':
323 case 'B':
324 case 'C':
325 case 'S':
326 case 'I':
327 *reinterpret_cast<int32_t*>(&arg_array[offset]) = va_arg(ap, jint);
328 offset += 4;
329 break;
330 case 'F':
331 *reinterpret_cast<float*>(&arg_array[offset]) = va_arg(ap, jdouble);
332 offset += 4;
333 break;
334 case 'L': {
Elliott Hughesc5f7c912011-08-18 14:00:42 -0700335 Object* obj = Decode<Object*>(ts, va_arg(ap, jobject));
Carl Shapiro9b9ba282011-08-14 15:30:39 -0700336 *reinterpret_cast<Object**>(&arg_array[offset]) = obj;
337 offset += sizeof(Object*);
338 break;
339 }
340 case 'D':
341 *reinterpret_cast<double*>(&arg_array[offset]) = va_arg(ap, jdouble);
342 offset += 8;
343 break;
344 case 'J':
345 *reinterpret_cast<int64_t*>(&arg_array[offset]) = va_arg(ap, jlong);
346 offset += 8;
347 break;
348 }
349 }
350 return arg_array.release();
351}
352
Elliott Hughesc5f7c912011-08-18 14:00:42 -0700353byte* CreateArgArray(ScopedJniThreadState& ts, Method* method, jvalue* args) {
Carl Shapiro9b9ba282011-08-14 15:30:39 -0700354 size_t num_bytes = method->NumArgArrayBytes();
355 scoped_array<byte> arg_array(new byte[num_bytes]);
356 const StringPiece& shorty = method->GetShorty();
Ian Rogers4dd71f12011-08-16 14:16:02 -0700357 for (int i = 1, offset = 0; i < shorty.size(); ++i) {
Carl Shapiro9b9ba282011-08-14 15:30:39 -0700358 switch (shorty[i]) {
359 case 'Z':
360 case 'B':
361 case 'C':
362 case 'S':
363 case 'I':
364 *reinterpret_cast<uint32_t*>(&arg_array[offset]) = args[i - 1].i;
365 offset += 4;
366 break;
367 case 'F':
368 *reinterpret_cast<float*>(&arg_array[offset]) = args[i - 1].f;
369 offset += 4;
370 break;
371 case 'L': {
Elliott Hughesc5f7c912011-08-18 14:00:42 -0700372 Object* obj = Decode<Object*>(ts, args[i - 1].l);
Carl Shapiro9b9ba282011-08-14 15:30:39 -0700373 *reinterpret_cast<Object**>(&arg_array[offset]) = obj;
374 offset += sizeof(Object*);
375 break;
376 }
377 case 'D':
378 *reinterpret_cast<double*>(&arg_array[offset]) = args[i - 1].d;
379 offset += 8;
380 break;
381 case 'J':
382 *reinterpret_cast<uint64_t*>(&arg_array[offset]) = args[i - 1].j;
383 offset += 8;
384 break;
385 }
386 }
387 return arg_array.release();
388}
389
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700390JValue InvokeWithArgArray(ScopedJniThreadState& ts, jobject obj,
Elliott Hughescdf53122011-08-19 15:46:09 -0700391 jmethodID mid, byte* args) {
392 Method* method = DecodeMethod(ts, mid);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700393 Object* rcvr = Decode<Object*>(ts, obj);
Ian Rogers6de08602011-08-19 14:52:39 -0700394 Thread* self = ts.Self();
395
396 // Push a transition back into managed code onto the linked list in thread
397 CHECK_EQ(Thread::kRunnable, self->GetState());
398 NativeToManagedRecord record;
399 self->PushNativeToManagedRecord(&record);
400
Carl Shapiro9b9ba282011-08-14 15:30:39 -0700401 // Call the invoke stub associated with the method
402 // Pass everything as arguments
403 const Method::InvokeStub* stub = method->GetInvokeStub();
404 CHECK(stub != NULL);
buzbeec143c552011-08-20 17:38:58 -0700405
406#ifdef __arm__
407 // Compile...
408 // TODO: not here!
409 oatCompileMethod(method, kThumb2);
410#endif
411
Carl Shapiro9b9ba282011-08-14 15:30:39 -0700412 JValue result;
buzbeec143c552011-08-20 17:38:58 -0700413 if (method->HasCode()) {
Ian Rogers6de08602011-08-19 14:52:39 -0700414 (*stub)(method, rcvr, self, args, &result);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700415 } else {
Elliott Hughesa0b8feb2011-08-20 09:50:55 -0700416 LOG(WARNING) << "Not invoking method with no associated code: "
417 << PrettyMethod(method, true);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700418 result.j = 0;
419 }
buzbeec143c552011-08-20 17:38:58 -0700420
Ian Rogers6de08602011-08-19 14:52:39 -0700421 // Pop transition
422 self->PopNativeToManagedRecord(record);
Carl Shapiro9b9ba282011-08-14 15:30:39 -0700423 return result;
424}
425
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700426JValue InvokeWithJValues(ScopedJniThreadState& ts, jobject obj,
Elliott Hughescdf53122011-08-19 15:46:09 -0700427 jmethodID mid, jvalue* args) {
428 Method* method = DecodeMethod(ts, mid);
Elliott Hughesc5f7c912011-08-18 14:00:42 -0700429 scoped_array<byte> arg_array(CreateArgArray(ts, method, args));
Elliott Hughescdf53122011-08-19 15:46:09 -0700430 return InvokeWithArgArray(ts, obj, mid, arg_array.get());
Carl Shapiro9b9ba282011-08-14 15:30:39 -0700431}
432
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700433JValue InvokeWithVarArgs(ScopedJniThreadState& ts, jobject obj,
Elliott Hughescdf53122011-08-19 15:46:09 -0700434 jmethodID mid, va_list args) {
435 Method* method = DecodeMethod(ts, mid);
Elliott Hughesc5f7c912011-08-18 14:00:42 -0700436 scoped_array<byte> arg_array(CreateArgArray(ts, method, args));
Elliott Hughescdf53122011-08-19 15:46:09 -0700437 return InvokeWithArgArray(ts, obj, mid, arg_array.get());
Carl Shapiroea4dca82011-08-01 13:45:38 -0700438}
439
Elliott Hughes6b436852011-08-12 10:16:44 -0700440// Section 12.3.2 of the JNI spec describes JNI class descriptors. They're
441// separated with slashes but aren't wrapped with "L;" like regular descriptors
442// (i.e. "a/b/C" rather than "La/b/C;"). Arrays of reference types are an
443// exception; there the "L;" must be present ("[La/b/C;"). Historically we've
444// supported names with dots too (such as "a.b.C").
445std::string NormalizeJniClassDescriptor(const char* name) {
446 std::string result;
447 // Add the missing "L;" if necessary.
448 if (name[0] == '[') {
449 result = name;
450 } else {
451 result += 'L';
452 result += name;
453 result += ';';
454 }
455 // Rewrite '.' as '/' for backwards compatibility.
Elliott Hughesa5b897e2011-08-16 11:33:06 -0700456 if (result.find('.') != std::string::npos) {
457 LOG(WARNING) << "Call to JNI FindClass with dots in name: "
458 << "\"" << name << "\"";
459 std::replace(result.begin(), result.end(), '.', '/');
Elliott Hughes6b436852011-08-12 10:16:44 -0700460 }
461 return result;
462}
463
Elliott Hughescdf53122011-08-19 15:46:09 -0700464jmethodID FindMethodID(ScopedJniThreadState& ts, jclass jni_class, const char* name, const char* sig, bool is_static) {
465 Class* c = Decode<Class*>(ts, jni_class);
Elliott Hughesf4c21c92011-08-19 17:31:31 -0700466 if (!Runtime::Current()->GetClassLinker()->EnsureInitialized(c)) {
467 return NULL;
Carl Shapiro83ab4f32011-08-15 20:21:39 -0700468 }
Elliott Hughescdf53122011-08-19 15:46:09 -0700469
470 Method* method = NULL;
471 if (is_static) {
472 method = c->FindDirectMethod(name, sig);
Ian Rogers4dd71f12011-08-16 14:16:02 -0700473 } else {
Elliott Hughescdf53122011-08-19 15:46:09 -0700474 method = c->FindVirtualMethod(name, sig);
475 if (method == NULL) {
476 // No virtual method matching the signature. Search declared
477 // private methods and constructors.
478 method = c->FindDeclaredDirectMethod(name, sig);
Ian Rogers4dd71f12011-08-16 14:16:02 -0700479 }
Carl Shapiro83ab4f32011-08-15 20:21:39 -0700480 }
Carl Shapiroea4dca82011-08-01 13:45:38 -0700481
Elliott Hughescdf53122011-08-19 15:46:09 -0700482 if (method == NULL || method->IsStatic() != is_static) {
483 Thread* self = Thread::Current();
Elliott Hughesa0b8feb2011-08-20 09:50:55 -0700484 std::string method_name(PrettyMethod(method, true));
Elliott Hughescdf53122011-08-19 15:46:09 -0700485 // TODO: try searching for the opposite kind of method from is_static
486 // for better diagnostics?
487 self->ThrowNewException("Ljava/lang/NoSuchMethodError;",
Elliott Hughesa0b8feb2011-08-20 09:50:55 -0700488 "no %s method %s", is_static ? "static" : "non-static",
489 method_name.c_str());
Elliott Hughescdf53122011-08-19 15:46:09 -0700490 return NULL;
491 }
Carl Shapiroea4dca82011-08-01 13:45:38 -0700492
Elliott Hughescdf53122011-08-19 15:46:09 -0700493 bool success = EnsureInvokeStub(method);
494 if (!success) {
495 // TODO: throw OutOfMemoryException
496 return NULL;
497 }
Carl Shapiroea4dca82011-08-01 13:45:38 -0700498
Elliott Hughescdf53122011-08-19 15:46:09 -0700499 return reinterpret_cast<jmethodID>(AddWeakGlobalReference(ts, method));
Carl Shapiroea4dca82011-08-01 13:45:38 -0700500}
501
Elliott Hughescdf53122011-08-19 15:46:09 -0700502jfieldID FindFieldID(ScopedJniThreadState& ts, jclass jni_class, const char* name, const char* sig, bool is_static) {
503 Class* c = Decode<Class*>(ts, jni_class);
Elliott Hughesf4c21c92011-08-19 17:31:31 -0700504 if (!Runtime::Current()->GetClassLinker()->EnsureInitialized(c)) {
505 return NULL;
Carl Shapiro83ab4f32011-08-15 20:21:39 -0700506 }
Elliott Hughescdf53122011-08-19 15:46:09 -0700507
508 Field* field = NULL;
509 if (is_static) {
510 field = c->FindStaticField(name, sig);
Ian Rogers4dd71f12011-08-16 14:16:02 -0700511 } else {
Elliott Hughescdf53122011-08-19 15:46:09 -0700512 field = c->FindInstanceField(name, sig);
Carl Shapiro9b9ba282011-08-14 15:30:39 -0700513 }
Carl Shapiroea4dca82011-08-01 13:45:38 -0700514
Elliott Hughescdf53122011-08-19 15:46:09 -0700515 if (field == NULL) {
516 Thread* self = Thread::Current();
Elliott Hughese5b0dc82011-08-23 09:59:02 -0700517 std::string class_descriptor(c->GetDescriptor()->ToModifiedUtf8());
Elliott Hughescdf53122011-08-19 15:46:09 -0700518 self->ThrowNewException("Ljava/lang/NoSuchFieldError;",
519 "no \"%s\" field \"%s\" in class \"%s\" or its superclasses", sig,
Elliott Hughese5b0dc82011-08-23 09:59:02 -0700520 name, class_descriptor.c_str());
Elliott Hughes8a26c5c2011-08-15 18:35:43 -0700521 return NULL;
522 }
Carl Shapiroea4dca82011-08-01 13:45:38 -0700523
Elliott Hughescdf53122011-08-19 15:46:09 -0700524 jweak fid = AddWeakGlobalReference(ts, field);
525 return reinterpret_cast<jfieldID>(fid);
Carl Shapiroea4dca82011-08-01 13:45:38 -0700526}
527
Elliott Hughesd8ddfd52011-08-15 14:32:53 -0700528template<typename JniT, typename ArtT>
529JniT NewPrimitiveArray(ScopedJniThreadState& ts, jsize length) {
530 CHECK_GE(length, 0); // TODO: ReportJniError
531 ArtT* result = ArtT::Alloc(length);
Elliott Hughes8a26c5c2011-08-15 18:35:43 -0700532 return AddLocalReference<JniT>(ts, result);
Elliott Hughesd8ddfd52011-08-15 14:32:53 -0700533}
534
Elliott Hughes814e4032011-08-23 12:07:56 -0700535void ThrowAIOOBE(ScopedJniThreadState& ts, Array* array, jsize start, jsize length, const char* identifier) {
536 std::string type(PrettyType(array));
537 ts.Self()->ThrowNewException("Ljava/lang/ArrayIndexOutOfBoundsException;",
538 "%s offset=%d length=%d %s.length=%d",
539 type.c_str(), start, length, identifier, array->GetLength());
540}
541
542template <typename JavaArrayT, typename JavaT, typename ArrayT>
543static void GetPrimitiveArrayRegion(ScopedJniThreadState& ts, JavaArrayT java_array, jsize start, jsize length, JavaT* buf) {
544 ArrayT* array = Decode<ArrayT*>(ts, java_array);
545 if (start < 0 || length < 0 || start + length > array->GetLength()) {
546 ThrowAIOOBE(ts, array, start, length, "src");
547 } else {
548 JavaT* data = array->GetData();
549 memcpy(buf, data + start, length * sizeof(JavaT));
550 }
551}
552
553template <typename JavaArrayT, typename JavaT, typename ArrayT>
554static void SetPrimitiveArrayRegion(ScopedJniThreadState& ts, JavaArrayT java_array, jsize start, jsize length, const JavaT* buf) {
555 ArrayT* array = Decode<ArrayT*>(ts, java_array);
556 if (start < 0 || length < 0 || start + length > array->GetLength()) {
557 ThrowAIOOBE(ts, array, start, length, "dst");
558 } else {
559 JavaT* data = array->GetData();
560 memcpy(data + start, buf, length * sizeof(JavaT));
561 }
562}
563
Elliott Hughescdf53122011-08-19 15:46:09 -0700564} // namespace
Carl Shapiroea4dca82011-08-01 13:45:38 -0700565
Elliott Hughescdf53122011-08-19 15:46:09 -0700566class JNI {
567 public:
Carl Shapiroea4dca82011-08-01 13:45:38 -0700568
Elliott Hughescdf53122011-08-19 15:46:09 -0700569 static jint GetVersion(JNIEnv* env) {
570 ScopedJniThreadState ts(env);
571 return JNI_VERSION_1_6;
572 }
Carl Shapiroea4dca82011-08-01 13:45:38 -0700573
Elliott Hughescdf53122011-08-19 15:46:09 -0700574 static jclass DefineClass(JNIEnv* env, const char*, jobject, const jbyte*, jsize) {
575 ScopedJniThreadState ts(env);
576 LOG(WARNING) << "JNI DefineClass is not supported";
Elliott Hughesf2682d52011-08-15 16:37:04 -0700577 return NULL;
578 }
579
Elliott Hughescdf53122011-08-19 15:46:09 -0700580 static jclass FindClass(JNIEnv* env, const char* name) {
581 ScopedJniThreadState ts(env);
582 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
583 std::string descriptor(NormalizeJniClassDescriptor(name));
584 // TODO: need to get the appropriate ClassLoader.
Elliott Hughesedcc09c2011-08-21 18:47:05 -0700585 ClassLoader* cl = ts.Self()->GetClassLoaderOverride();
buzbeec143c552011-08-20 17:38:58 -0700586 Class* c = class_linker->FindClass(descriptor, cl);
Elliott Hughescdf53122011-08-19 15:46:09 -0700587 return AddLocalReference<jclass>(ts, c);
Ian Rogers4dd71f12011-08-16 14:16:02 -0700588 }
Carl Shapiroea4dca82011-08-01 13:45:38 -0700589
Elliott Hughescdf53122011-08-19 15:46:09 -0700590 static jmethodID FromReflectedMethod(JNIEnv* env, jobject java_method) {
591 ScopedJniThreadState ts(env);
592 Method* method = Decode<Method*>(ts, java_method);
593 return reinterpret_cast<jmethodID>(AddWeakGlobalReference(ts, method));
Elliott Hughesf2682d52011-08-15 16:37:04 -0700594 }
Carl Shapiroea4dca82011-08-01 13:45:38 -0700595
Elliott Hughescdf53122011-08-19 15:46:09 -0700596 static jfieldID FromReflectedField(JNIEnv* env, jobject java_field) {
597 ScopedJniThreadState ts(env);
598 Field* field = Decode<Field*>(ts, java_field);
599 return reinterpret_cast<jfieldID>(AddWeakGlobalReference(ts, field));
600 }
Carl Shapiroea4dca82011-08-01 13:45:38 -0700601
Elliott Hughescdf53122011-08-19 15:46:09 -0700602 static jobject ToReflectedMethod(JNIEnv* env, jclass, jmethodID mid, jboolean) {
603 ScopedJniThreadState ts(env);
604 Method* method = DecodeMethod(ts, mid);
605 return AddLocalReference<jobject>(ts, method);
606 }
Carl Shapiroea4dca82011-08-01 13:45:38 -0700607
Elliott Hughescdf53122011-08-19 15:46:09 -0700608 static jobject ToReflectedField(JNIEnv* env, jclass, jfieldID fid, jboolean) {
609 ScopedJniThreadState ts(env);
610 Field* field = DecodeField(ts, fid);
611 return AddLocalReference<jobject>(ts, field);
612 }
Carl Shapiroea4dca82011-08-01 13:45:38 -0700613
Elliott Hughes37f7a402011-08-22 18:56:01 -0700614 static jclass GetObjectClass(JNIEnv* env, jobject java_object) {
615 ScopedJniThreadState ts(env);
616 Object* o = Decode<Object*>(ts, java_object);
617 return AddLocalReference<jclass>(ts, o->GetClass());
618 }
619
Elliott Hughes885c3bd2011-08-22 16:59:20 -0700620 static jclass GetSuperclass(JNIEnv* env, jclass java_class) {
Elliott Hughescdf53122011-08-19 15:46:09 -0700621 ScopedJniThreadState ts(env);
Elliott Hughes885c3bd2011-08-22 16:59:20 -0700622 Class* c = Decode<Class*>(ts, java_class);
623 return AddLocalReference<jclass>(ts, c->GetSuperClass());
Elliott Hughescdf53122011-08-19 15:46:09 -0700624 }
Carl Shapiroea4dca82011-08-01 13:45:38 -0700625
Elliott Hughes37f7a402011-08-22 18:56:01 -0700626 static jboolean IsAssignableFrom(JNIEnv* env, jclass java_class1, jclass java_class2) {
Elliott Hughescdf53122011-08-19 15:46:09 -0700627 ScopedJniThreadState ts(env);
Elliott Hughes37f7a402011-08-22 18:56:01 -0700628 Class* c1 = Decode<Class*>(ts, java_class1);
629 Class* c2 = Decode<Class*>(ts, java_class2);
630 return c1->IsAssignableFrom(c2) ? JNI_TRUE : JNI_FALSE;
Elliott Hughescdf53122011-08-19 15:46:09 -0700631 }
Carl Shapiroea4dca82011-08-01 13:45:38 -0700632
Elliott Hughes37f7a402011-08-22 18:56:01 -0700633 static jboolean IsInstanceOf(JNIEnv* env, jobject jobj, jclass clazz) {
Elliott Hughescdf53122011-08-19 15:46:09 -0700634 ScopedJniThreadState ts(env);
Elliott Hughes37f7a402011-08-22 18:56:01 -0700635 CHECK_NE(static_cast<jclass>(NULL), clazz);
636 if (jobj == NULL) {
637 // NB. JNI is different from regular Java instanceof in this respect
638 return JNI_TRUE;
639 } else {
640 Object* obj = Decode<Object*>(ts, jobj);
641 Class* klass = Decode<Class*>(ts, clazz);
642 return Object::InstanceOf(obj, klass) ? JNI_TRUE : JNI_FALSE;
643 }
Elliott Hughescdf53122011-08-19 15:46:09 -0700644 }
Carl Shapiroea4dca82011-08-01 13:45:38 -0700645
Elliott Hughes37f7a402011-08-22 18:56:01 -0700646 static jint Throw(JNIEnv* env, jthrowable java_exception) {
647 ScopedJniThreadState ts(env);
Elliott Hughese5b0dc82011-08-23 09:59:02 -0700648 Throwable* exception = Decode<Throwable*>(ts, java_exception);
Elliott Hughes37f7a402011-08-22 18:56:01 -0700649 if (exception == NULL) {
650 return JNI_ERR;
651 }
652 ts.Self()->SetException(exception);
653 return JNI_OK;
654 }
655
Elliott Hughese5b0dc82011-08-23 09:59:02 -0700656 static jint ThrowNew(JNIEnv* env, jclass c, const char* msg) {
Elliott Hughes37f7a402011-08-22 18:56:01 -0700657 ScopedJniThreadState ts(env);
Elliott Hughese5b0dc82011-08-23 09:59:02 -0700658 // TODO: check for a pending exception to decide what constructor to call.
659 jmethodID mid = env->GetMethodID(c, "<init>", "(Ljava/lang/String;)V");
660 if (mid == NULL) {
661 return JNI_ERR;
662 }
663 jstring s = env->NewStringUTF(msg);
664 if (s == NULL) {
665 return JNI_ERR;
666 }
667
668 jvalue args[1];
669 args[0].l = s;
670 jthrowable exception = reinterpret_cast<jthrowable>(env->NewObjectA(c, mid, args));
671 if (exception == NULL) {
672 return JNI_ERR;
673 }
674
675 LOG(INFO) << "Throwing " << PrettyType(Decode<Throwable*>(ts, exception))
676 << ": " << msg;
677 ts.Self()->SetException(Decode<Throwable*>(ts, exception));
678
679 env->DeleteLocalRef(exception);
680 env->DeleteLocalRef(s);
681
Elliott Hughes37f7a402011-08-22 18:56:01 -0700682 return JNI_OK;
683 }
684
685 static jboolean ExceptionCheck(JNIEnv* env) {
686 ScopedJniThreadState ts(env);
687 return ts.Self()->IsExceptionPending() ? JNI_TRUE : JNI_FALSE;
688 }
689
690 static void ExceptionClear(JNIEnv* env) {
691 ScopedJniThreadState ts(env);
692 ts.Self()->ClearException();
693 }
694
695 static void ExceptionDescribe(JNIEnv* env) {
Elliott Hughescdf53122011-08-19 15:46:09 -0700696 ScopedJniThreadState ts(env);
697 UNIMPLEMENTED(FATAL);
Elliott Hughescdf53122011-08-19 15:46:09 -0700698 }
Carl Shapiroea4dca82011-08-01 13:45:38 -0700699
Elliott Hughescdf53122011-08-19 15:46:09 -0700700 static jthrowable ExceptionOccurred(JNIEnv* env) {
701 ScopedJniThreadState ts(env);
702 Object* exception = ts.Self()->GetException();
703 if (exception == NULL) {
704 return NULL;
705 } else {
706 // TODO: if adding a local reference failing causes the VM to abort
707 // then the following check will never occur.
708 jthrowable localException = AddLocalReference<jthrowable>(ts, exception);
709 if (localException == NULL) {
710 // We were unable to add a new local reference, and threw a new
711 // exception. We can't return "exception", because it's not a
712 // local reference. So we have to return NULL, indicating that
713 // there was no exception, even though it's pretty much raining
714 // exceptions in here.
715 LOG(WARNING) << "JNI WARNING: addLocal/exception combo";
716 }
717 return localException;
718 }
719 }
720
Elliott Hughescdf53122011-08-19 15:46:09 -0700721 static void FatalError(JNIEnv* env, const char* msg) {
722 ScopedJniThreadState ts(env);
723 LOG(FATAL) << "JNI FatalError called: " << msg;
724 }
725
726 static jint PushLocalFrame(JNIEnv* env, jint cap) {
727 ScopedJniThreadState ts(env);
728 UNIMPLEMENTED(WARNING) << "ignoring PushLocalFrame(" << cap << ")";
729 return JNI_OK;
730 }
731
732 static jobject PopLocalFrame(JNIEnv* env, jobject res) {
733 ScopedJniThreadState ts(env);
734 UNIMPLEMENTED(WARNING) << "ignoring PopLocalFrame " << res;
735 return res;
736 }
737
738 static jobject NewGlobalRef(JNIEnv* env, jobject obj) {
739 ScopedJniThreadState ts(env);
740 if (obj == NULL) {
741 return NULL;
742 }
743
744 JavaVMExt* vm = Runtime::Current()->GetJavaVM();
745 IndirectReferenceTable& globals = vm->globals;
746 MutexLock mu(vm->globals_lock);
747 IndirectRef ref = globals.Add(IRT_FIRST_SEGMENT, Decode<Object*>(ts, obj));
748 return reinterpret_cast<jobject>(ref);
749 }
750
751 static void DeleteGlobalRef(JNIEnv* env, jobject obj) {
752 ScopedJniThreadState ts(env);
753 if (obj == NULL) {
754 return;
755 }
756
757 JavaVMExt* vm = Runtime::Current()->GetJavaVM();
758 IndirectReferenceTable& globals = vm->globals;
759 MutexLock mu(vm->globals_lock);
760
761 if (!globals.Remove(IRT_FIRST_SEGMENT, obj)) {
762 LOG(WARNING) << "JNI WARNING: DeleteGlobalRef(" << obj << ") "
763 << "failed to find entry";
764 }
765 }
766
767 static jweak NewWeakGlobalRef(JNIEnv* env, jobject obj) {
768 ScopedJniThreadState ts(env);
769 return AddWeakGlobalReference(ts, Decode<Object*>(ts, obj));
770 }
771
772 static void DeleteWeakGlobalRef(JNIEnv* env, jweak obj) {
773 ScopedJniThreadState ts(env);
774 if (obj == NULL) {
775 return;
776 }
777
778 JavaVMExt* vm = Runtime::Current()->GetJavaVM();
779 IndirectReferenceTable& weak_globals = vm->weak_globals;
780 MutexLock mu(vm->weak_globals_lock);
781
782 if (!weak_globals.Remove(IRT_FIRST_SEGMENT, obj)) {
783 LOG(WARNING) << "JNI WARNING: DeleteWeakGlobalRef(" << obj << ") "
784 << "failed to find entry";
785 }
786 }
787
788 static jobject NewLocalRef(JNIEnv* env, jobject obj) {
789 ScopedJniThreadState ts(env);
790 if (obj == NULL) {
791 return NULL;
792 }
793
794 IndirectReferenceTable& locals = ts.Env()->locals;
795
796 uint32_t cookie = IRT_FIRST_SEGMENT; // TODO
797 IndirectRef ref = locals.Add(cookie, Decode<Object*>(ts, obj));
798 return reinterpret_cast<jobject>(ref);
799 }
800
801 static void DeleteLocalRef(JNIEnv* env, jobject obj) {
802 ScopedJniThreadState ts(env);
803 if (obj == NULL) {
804 return;
805 }
806
807 IndirectReferenceTable& locals = ts.Env()->locals;
808
809 uint32_t cookie = IRT_FIRST_SEGMENT; // TODO
810 if (!locals.Remove(cookie, obj)) {
811 // Attempting to delete a local reference that is not in the
812 // topmost local reference frame is a no-op. DeleteLocalRef returns
813 // void and doesn't throw any exceptions, but we should probably
814 // complain about it so the user will notice that things aren't
815 // going quite the way they expect.
816 LOG(WARNING) << "JNI WARNING: DeleteLocalRef(" << obj << ") "
817 << "failed to find entry";
818 }
819 }
820
821 static jboolean IsSameObject(JNIEnv* env, jobject obj1, jobject obj2) {
822 ScopedJniThreadState ts(env);
823 return (Decode<Object*>(ts, obj1) == Decode<Object*>(ts, obj2))
824 ? JNI_TRUE : JNI_FALSE;
825 }
826
827 static jint EnsureLocalCapacity(JNIEnv* env, jint) {
828 ScopedJniThreadState ts(env);
829 UNIMPLEMENTED(FATAL);
830 return 0;
831 }
832
Elliott Hughes885c3bd2011-08-22 16:59:20 -0700833 static jobject AllocObject(JNIEnv* env, jclass java_class) {
Elliott Hughescdf53122011-08-19 15:46:09 -0700834 ScopedJniThreadState ts(env);
Elliott Hughes885c3bd2011-08-22 16:59:20 -0700835 Class* c = Decode<Class*>(ts, java_class);
836 if (!Runtime::Current()->GetClassLinker()->EnsureInitialized(c)) {
837 return NULL;
838 }
839 return AddLocalReference<jobject>(ts, c->NewInstance());
Elliott Hughescdf53122011-08-19 15:46:09 -0700840 }
841
842 static jobject NewObject(JNIEnv* env, jclass clazz, jmethodID methodID, ...) {
843 ScopedJniThreadState ts(env);
844 va_list args;
845 va_start(args, methodID);
846 jobject result = NewObjectV(env, clazz, methodID, args);
847 va_end(args);
848 return result;
849 }
850
Elliott Hughes885c3bd2011-08-22 16:59:20 -0700851 static jobject NewObjectV(JNIEnv* env, jclass java_class, jmethodID methodID, va_list args) {
Elliott Hughescdf53122011-08-19 15:46:09 -0700852 ScopedJniThreadState ts(env);
Elliott Hughes885c3bd2011-08-22 16:59:20 -0700853 Class* c = Decode<Class*>(ts, java_class);
854 if (!Runtime::Current()->GetClassLinker()->EnsureInitialized(c)) {
855 return NULL;
856 }
857 Object* result = c->NewInstance();
Elliott Hughescdf53122011-08-19 15:46:09 -0700858 jobject local_result = AddLocalReference<jobject>(ts, result);
Elliott Hughes885c3bd2011-08-22 16:59:20 -0700859 CallNonvirtualVoidMethodV(env, local_result, java_class, methodID, args);
Elliott Hughescdf53122011-08-19 15:46:09 -0700860 return local_result;
861 }
862
Elliott Hughes885c3bd2011-08-22 16:59:20 -0700863 static jobject NewObjectA(JNIEnv* env, jclass java_class, jmethodID methodID, jvalue* args) {
Elliott Hughescdf53122011-08-19 15:46:09 -0700864 ScopedJniThreadState ts(env);
Elliott Hughes885c3bd2011-08-22 16:59:20 -0700865 Class* c = Decode<Class*>(ts, java_class);
866 if (!Runtime::Current()->GetClassLinker()->EnsureInitialized(c)) {
867 return NULL;
868 }
869 Object* result = c->NewInstance();
Elliott Hughescdf53122011-08-19 15:46:09 -0700870 jobject local_result = AddLocalReference<jobjectArray>(ts, result);
Elliott Hughes885c3bd2011-08-22 16:59:20 -0700871 CallNonvirtualVoidMethodA(env, local_result, java_class, methodID, args);
Elliott Hughescdf53122011-08-19 15:46:09 -0700872 return local_result;
873 }
874
Elliott Hughescdf53122011-08-19 15:46:09 -0700875 static jmethodID GetMethodID(JNIEnv* env, jclass c, const char* name, const char* sig) {
876 ScopedJniThreadState ts(env);
877 return FindMethodID(ts, c, name, sig, false);
878 }
879
880 static jmethodID GetStaticMethodID(JNIEnv* env, jclass c, const char* name, const char* sig) {
881 ScopedJniThreadState ts(env);
882 return FindMethodID(ts, c, name, sig, true);
883 }
884
885 static jobject CallObjectMethod(JNIEnv* env, jobject obj, jmethodID methodID, ...) {
886 ScopedJniThreadState ts(env);
887 UNIMPLEMENTED(FATAL);
888 return NULL;
889 }
890
891 static jobject CallObjectMethodV(JNIEnv* env,
892 jobject obj, jmethodID methodID, va_list args) {
893 ScopedJniThreadState ts(env);
894 UNIMPLEMENTED(FATAL);
895 return NULL;
896 }
897
898 static jobject CallObjectMethodA(JNIEnv* env,
899 jobject obj, jmethodID methodID, jvalue* args) {
900 ScopedJniThreadState ts(env);
901 UNIMPLEMENTED(FATAL);
902 return NULL;
903 }
904
905 static jboolean CallBooleanMethod(JNIEnv* env, jobject obj, jmethodID methodID, ...) {
906 ScopedJniThreadState ts(env);
907 UNIMPLEMENTED(FATAL);
908 return JNI_FALSE;
909 }
910
911 static jboolean CallBooleanMethodV(JNIEnv* env,
912 jobject obj, jmethodID methodID, va_list args) {
913 ScopedJniThreadState ts(env);
914 UNIMPLEMENTED(FATAL);
915 return JNI_FALSE;
916 }
917
918 static jboolean CallBooleanMethodA(JNIEnv* env,
919 jobject obj, jmethodID methodID, jvalue* args) {
920 ScopedJniThreadState ts(env);
921 UNIMPLEMENTED(FATAL);
922 return JNI_FALSE;
923 }
924
925 static jbyte CallByteMethod(JNIEnv* env, jobject obj, jmethodID methodID, ...) {
926 ScopedJniThreadState ts(env);
927 UNIMPLEMENTED(FATAL);
928 return 0;
929 }
930
931 static jbyte CallByteMethodV(JNIEnv* env,
932 jobject obj, jmethodID methodID, va_list args) {
933 ScopedJniThreadState ts(env);
934 UNIMPLEMENTED(FATAL);
935 return 0;
936 }
937
938 static jbyte CallByteMethodA(JNIEnv* env,
939 jobject obj, jmethodID methodID, jvalue* args) {
940 ScopedJniThreadState ts(env);
941 UNIMPLEMENTED(FATAL);
942 return 0;
943 }
944
945 static jchar CallCharMethod(JNIEnv* env, jobject obj, jmethodID methodID, ...) {
946 ScopedJniThreadState ts(env);
947 UNIMPLEMENTED(FATAL);
948 return 0;
949 }
950
951 static jchar CallCharMethodV(JNIEnv* env,
952 jobject obj, jmethodID methodID, va_list args) {
953 ScopedJniThreadState ts(env);
954 UNIMPLEMENTED(FATAL);
955 return 0;
956 }
957
958 static jchar CallCharMethodA(JNIEnv* env,
959 jobject obj, jmethodID methodID, jvalue* args) {
960 ScopedJniThreadState ts(env);
961 UNIMPLEMENTED(FATAL);
962 return 0;
963 }
964
965 static jshort CallShortMethod(JNIEnv* env, jobject obj, jmethodID methodID, ...) {
966 ScopedJniThreadState ts(env);
967 UNIMPLEMENTED(FATAL);
968 return 0;
969 }
970
971 static jshort CallShortMethodV(JNIEnv* env,
972 jobject obj, jmethodID methodID, va_list args) {
973 ScopedJniThreadState ts(env);
974 UNIMPLEMENTED(FATAL);
975 return 0;
976 }
977
978 static jshort CallShortMethodA(JNIEnv* env,
979 jobject obj, jmethodID methodID, jvalue* args) {
980 ScopedJniThreadState ts(env);
981 UNIMPLEMENTED(FATAL);
982 return 0;
983 }
984
985 static jint CallIntMethod(JNIEnv* env, jobject obj, jmethodID methodID, ...) {
986 ScopedJniThreadState ts(env);
987 UNIMPLEMENTED(FATAL);
988 return 0;
989 }
990
991 static jint CallIntMethodV(JNIEnv* env,
992 jobject obj, jmethodID methodID, va_list args) {
993 ScopedJniThreadState ts(env);
994 UNIMPLEMENTED(FATAL);
995 return 0;
996 }
997
998 static jint CallIntMethodA(JNIEnv* env,
999 jobject obj, jmethodID methodID, jvalue* args) {
1000 ScopedJniThreadState ts(env);
1001 UNIMPLEMENTED(FATAL);
1002 return 0;
1003 }
1004
1005 static jlong CallLongMethod(JNIEnv* env, jobject obj, jmethodID methodID, ...) {
1006 ScopedJniThreadState ts(env);
1007 UNIMPLEMENTED(FATAL);
1008 return 0;
1009 }
1010
1011 static jlong CallLongMethodV(JNIEnv* env,
1012 jobject obj, jmethodID methodID, va_list args) {
1013 ScopedJniThreadState ts(env);
1014 UNIMPLEMENTED(FATAL);
1015 return 0;
1016 }
1017
1018 static jlong CallLongMethodA(JNIEnv* env,
1019 jobject obj, jmethodID methodID, jvalue* args) {
1020 ScopedJniThreadState ts(env);
1021 UNIMPLEMENTED(FATAL);
1022 return 0;
1023 }
1024
1025 static jfloat CallFloatMethod(JNIEnv* env, jobject obj, jmethodID methodID, ...) {
1026 ScopedJniThreadState ts(env);
1027 UNIMPLEMENTED(FATAL);
1028 return 0;
1029 }
1030
1031 static jfloat CallFloatMethodV(JNIEnv* env,
1032 jobject obj, jmethodID methodID, va_list args) {
1033 ScopedJniThreadState ts(env);
1034 UNIMPLEMENTED(FATAL);
1035 return 0;
1036 }
1037
1038 static jfloat CallFloatMethodA(JNIEnv* env,
1039 jobject obj, jmethodID methodID, jvalue* args) {
1040 ScopedJniThreadState ts(env);
1041 UNIMPLEMENTED(FATAL);
1042 return 0;
1043 }
1044
1045 static jdouble CallDoubleMethod(JNIEnv* env, jobject obj, jmethodID methodID, ...) {
1046 ScopedJniThreadState ts(env);
1047 UNIMPLEMENTED(FATAL);
1048 return 0;
1049 }
1050
1051 static jdouble CallDoubleMethodV(JNIEnv* env,
1052 jobject obj, jmethodID methodID, va_list args) {
1053 ScopedJniThreadState ts(env);
1054 UNIMPLEMENTED(FATAL);
1055 return 0;
1056 }
1057
1058 static jdouble CallDoubleMethodA(JNIEnv* env,
1059 jobject obj, jmethodID methodID, jvalue* args) {
1060 ScopedJniThreadState ts(env);
1061 UNIMPLEMENTED(FATAL);
1062 return 0;
1063 }
1064
1065 static void CallVoidMethod(JNIEnv* env, jobject obj, jmethodID methodID, ...) {
1066 ScopedJniThreadState ts(env);
1067 UNIMPLEMENTED(FATAL);
1068 }
1069
1070 static void CallVoidMethodV(JNIEnv* env, jobject obj,
1071 jmethodID methodID, va_list args) {
1072 ScopedJniThreadState ts(env);
1073 UNIMPLEMENTED(FATAL);
1074 }
1075
1076 static void CallVoidMethodA(JNIEnv* env, jobject obj,
1077 jmethodID methodID, jvalue* args) {
1078 ScopedJniThreadState ts(env);
1079 UNIMPLEMENTED(FATAL);
1080 }
1081
1082 static jobject CallNonvirtualObjectMethod(JNIEnv* env,
1083 jobject obj, jclass clazz, jmethodID methodID, ...) {
1084 ScopedJniThreadState ts(env);
1085 va_list ap;
1086 va_start(ap, methodID);
1087 JValue result = InvokeWithVarArgs(ts, obj, methodID, ap);
1088 jobject local_result = AddLocalReference<jobject>(ts, result.l);
1089 va_end(ap);
1090 return local_result;
1091 }
1092
1093 static jobject CallNonvirtualObjectMethodV(JNIEnv* env,
1094 jobject obj, jclass clazz, jmethodID methodID, va_list args) {
1095 ScopedJniThreadState ts(env);
1096 JValue result = InvokeWithVarArgs(ts, obj, methodID, args);
1097 return AddLocalReference<jobject>(ts, result.l);
1098 }
1099
1100 static jobject CallNonvirtualObjectMethodA(JNIEnv* env,
1101 jobject obj, jclass clazz, jmethodID methodID, jvalue* args) {
1102 ScopedJniThreadState ts(env);
1103 JValue result = InvokeWithJValues(ts, obj, methodID, args);
1104 return AddLocalReference<jobject>(ts, result.l);
1105 }
1106
1107 static jboolean CallNonvirtualBooleanMethod(JNIEnv* env,
1108 jobject obj, jclass clazz, jmethodID methodID, ...) {
1109 ScopedJniThreadState ts(env);
1110 va_list ap;
1111 va_start(ap, methodID);
1112 JValue result = InvokeWithVarArgs(ts, obj, methodID, ap);
1113 va_end(ap);
1114 return result.z;
1115 }
1116
1117 static jboolean CallNonvirtualBooleanMethodV(JNIEnv* env,
1118 jobject obj, jclass clazz, jmethodID methodID, va_list args) {
1119 ScopedJniThreadState ts(env);
1120 return InvokeWithVarArgs(ts, obj, methodID, args).z;
1121 }
1122
1123 static jboolean CallNonvirtualBooleanMethodA(JNIEnv* env,
1124 jobject obj, jclass clazz, jmethodID methodID, jvalue* args) {
1125 ScopedJniThreadState ts(env);
1126 return InvokeWithJValues(ts, obj, methodID, args).z;
1127 }
1128
1129 static jbyte CallNonvirtualByteMethod(JNIEnv* env,
1130 jobject obj, jclass clazz, jmethodID methodID, ...) {
1131 ScopedJniThreadState ts(env);
1132 va_list ap;
1133 va_start(ap, methodID);
1134 JValue result = InvokeWithVarArgs(ts, obj, methodID, ap);
1135 va_end(ap);
1136 return result.b;
1137 }
1138
1139 static jbyte CallNonvirtualByteMethodV(JNIEnv* env,
1140 jobject obj, jclass clazz, jmethodID methodID, va_list args) {
1141 ScopedJniThreadState ts(env);
1142 return InvokeWithVarArgs(ts, obj, methodID, args).b;
1143 }
1144
1145 static jbyte CallNonvirtualByteMethodA(JNIEnv* env,
1146 jobject obj, jclass clazz, jmethodID methodID, jvalue* args) {
1147 ScopedJniThreadState ts(env);
1148 return InvokeWithJValues(ts, obj, methodID, args).b;
1149 }
1150
1151 static jchar CallNonvirtualCharMethod(JNIEnv* env,
1152 jobject obj, jclass clazz, jmethodID methodID, ...) {
1153 ScopedJniThreadState ts(env);
1154 va_list ap;
1155 va_start(ap, methodID);
1156 JValue result = InvokeWithVarArgs(ts, obj, methodID, ap);
1157 va_end(ap);
1158 return result.c;
1159 }
1160
1161 static jchar CallNonvirtualCharMethodV(JNIEnv* env,
1162 jobject obj, jclass clazz, jmethodID methodID, va_list args) {
1163 ScopedJniThreadState ts(env);
1164 return InvokeWithVarArgs(ts, obj, methodID, args).c;
1165 }
1166
1167 static jchar CallNonvirtualCharMethodA(JNIEnv* env,
1168 jobject obj, jclass clazz, jmethodID methodID, jvalue* args) {
1169 ScopedJniThreadState ts(env);
1170 return InvokeWithJValues(ts, obj, methodID, args).c;
1171 }
1172
1173 static jshort CallNonvirtualShortMethod(JNIEnv* env,
1174 jobject obj, jclass clazz, jmethodID methodID, ...) {
1175 ScopedJniThreadState ts(env);
1176 va_list ap;
1177 va_start(ap, methodID);
1178 JValue result = InvokeWithVarArgs(ts, obj, methodID, ap);
1179 va_end(ap);
1180 return result.s;
1181 }
1182
1183 static jshort CallNonvirtualShortMethodV(JNIEnv* env,
1184 jobject obj, jclass clazz, jmethodID methodID, va_list args) {
1185 ScopedJniThreadState ts(env);
1186 return InvokeWithVarArgs(ts, obj, methodID, args).s;
1187 }
1188
1189 static jshort CallNonvirtualShortMethodA(JNIEnv* env,
1190 jobject obj, jclass clazz, jmethodID methodID, jvalue* args) {
1191 ScopedJniThreadState ts(env);
1192 return InvokeWithJValues(ts, obj, methodID, args).s;
1193 }
1194
1195 static jint CallNonvirtualIntMethod(JNIEnv* env,
1196 jobject obj, jclass clazz, jmethodID methodID, ...) {
1197 ScopedJniThreadState ts(env);
1198 va_list ap;
1199 va_start(ap, methodID);
1200 JValue result = InvokeWithVarArgs(ts, obj, methodID, ap);
1201 va_end(ap);
1202 return result.i;
1203 }
1204
1205 static jint CallNonvirtualIntMethodV(JNIEnv* env,
1206 jobject obj, jclass clazz, jmethodID methodID, va_list args) {
1207 ScopedJniThreadState ts(env);
1208 return InvokeWithVarArgs(ts, obj, methodID, args).i;
1209 }
1210
1211 static jint CallNonvirtualIntMethodA(JNIEnv* env,
1212 jobject obj, jclass clazz, jmethodID methodID, jvalue* args) {
1213 ScopedJniThreadState ts(env);
1214 return InvokeWithJValues(ts, obj, methodID, args).i;
1215 }
1216
1217 static jlong CallNonvirtualLongMethod(JNIEnv* env,
1218 jobject obj, jclass clazz, jmethodID methodID, ...) {
1219 ScopedJniThreadState ts(env);
1220 va_list ap;
1221 va_start(ap, methodID);
1222 JValue result = InvokeWithVarArgs(ts, obj, methodID, ap);
1223 va_end(ap);
1224 return result.j;
1225 }
1226
1227 static jlong CallNonvirtualLongMethodV(JNIEnv* env,
1228 jobject obj, jclass clazz, jmethodID methodID, va_list args) {
1229 ScopedJniThreadState ts(env);
1230 return InvokeWithVarArgs(ts, obj, methodID, args).j;
1231 }
1232
1233 static jlong CallNonvirtualLongMethodA(JNIEnv* env,
1234 jobject obj, jclass clazz, jmethodID methodID, jvalue* args) {
1235 ScopedJniThreadState ts(env);
1236 return InvokeWithJValues(ts, obj, methodID, args).j;
1237 }
1238
1239 static jfloat CallNonvirtualFloatMethod(JNIEnv* env,
1240 jobject obj, jclass clazz, jmethodID methodID, ...) {
1241 ScopedJniThreadState ts(env);
1242 va_list ap;
1243 va_start(ap, methodID);
1244 JValue result = InvokeWithVarArgs(ts, obj, methodID, ap);
1245 va_end(ap);
1246 return result.f;
1247 }
1248
1249 static jfloat CallNonvirtualFloatMethodV(JNIEnv* env,
1250 jobject obj, jclass clazz, jmethodID methodID, va_list args) {
1251 ScopedJniThreadState ts(env);
1252 return InvokeWithVarArgs(ts, obj, methodID, args).f;
1253 }
1254
1255 static jfloat CallNonvirtualFloatMethodA(JNIEnv* env,
1256 jobject obj, jclass clazz, jmethodID methodID, jvalue* args) {
1257 ScopedJniThreadState ts(env);
1258 return InvokeWithJValues(ts, obj, methodID, args).f;
1259 }
1260
1261 static jdouble CallNonvirtualDoubleMethod(JNIEnv* env,
1262 jobject obj, jclass clazz, jmethodID methodID, ...) {
1263 ScopedJniThreadState ts(env);
1264 va_list ap;
1265 va_start(ap, methodID);
1266 JValue result = InvokeWithVarArgs(ts, obj, methodID, ap);
1267 va_end(ap);
1268 return result.d;
1269 }
1270
1271 static jdouble CallNonvirtualDoubleMethodV(JNIEnv* env,
1272 jobject obj, jclass clazz, jmethodID methodID, va_list args) {
1273 ScopedJniThreadState ts(env);
1274 return InvokeWithVarArgs(ts, obj, methodID, args).d;
1275 }
1276
1277 static jdouble CallNonvirtualDoubleMethodA(JNIEnv* env,
1278 jobject obj, jclass clazz, jmethodID methodID, jvalue* args) {
1279 ScopedJniThreadState ts(env);
1280 return InvokeWithJValues(ts, obj, methodID, args).d;
1281 }
1282
1283 static void CallNonvirtualVoidMethod(JNIEnv* env,
1284 jobject obj, jclass clazz, jmethodID methodID, ...) {
1285 ScopedJniThreadState ts(env);
1286 va_list ap;
1287 va_start(ap, methodID);
1288 InvokeWithVarArgs(ts, obj, methodID, ap);
1289 va_end(ap);
1290 }
1291
1292 static void CallNonvirtualVoidMethodV(JNIEnv* env,
1293 jobject obj, jclass clazz, jmethodID methodID, va_list args) {
1294 ScopedJniThreadState ts(env);
1295 InvokeWithVarArgs(ts, obj, methodID, args);
1296 }
1297
1298 static void CallNonvirtualVoidMethodA(JNIEnv* env,
1299 jobject obj, jclass clazz, jmethodID methodID, jvalue* args) {
1300 ScopedJniThreadState ts(env);
1301 InvokeWithJValues(ts, obj, methodID, args);
1302 }
1303
1304 static jfieldID GetFieldID(JNIEnv* env,
1305 jclass c, const char* name, const char* sig) {
1306 ScopedJniThreadState ts(env);
1307 return FindFieldID(ts, c, name, sig, false);
1308 }
Carl Shapiroea4dca82011-08-01 13:45:38 -07001309
1310
Elliott Hughescdf53122011-08-19 15:46:09 -07001311 static jfieldID GetStaticFieldID(JNIEnv* env,
1312 jclass c, const char* name, const char* sig) {
1313 ScopedJniThreadState ts(env);
1314 return FindFieldID(ts, c, name, sig, true);
1315 }
Carl Shapiroea4dca82011-08-01 13:45:38 -07001316
Elliott Hughes885c3bd2011-08-22 16:59:20 -07001317 static jobject GetObjectField(JNIEnv* env, jobject obj, jfieldID fid) {
Elliott Hughescdf53122011-08-19 15:46:09 -07001318 ScopedJniThreadState ts(env);
Elliott Hughes885c3bd2011-08-22 16:59:20 -07001319 Object* o = Decode<Object*>(ts, obj);
1320 Field* f = DecodeField(ts, fid);
1321 return AddLocalReference<jobject>(ts, f->GetObject(o));
Elliott Hughescdf53122011-08-19 15:46:09 -07001322 }
Carl Shapiroea4dca82011-08-01 13:45:38 -07001323
Elliott Hughes885c3bd2011-08-22 16:59:20 -07001324 static jobject GetStaticObjectField(JNIEnv* env, jclass, jfieldID fid) {
Elliott Hughescdf53122011-08-19 15:46:09 -07001325 ScopedJniThreadState ts(env);
Elliott Hughes885c3bd2011-08-22 16:59:20 -07001326 Field* f = DecodeField(ts, fid);
1327 return AddLocalReference<jobject>(ts, f->GetObject(NULL));
Elliott Hughescdf53122011-08-19 15:46:09 -07001328 }
1329
Elliott Hughes885c3bd2011-08-22 16:59:20 -07001330 static void SetObjectField(JNIEnv* env, jobject java_object, jfieldID fid, jobject java_value) {
Elliott Hughescdf53122011-08-19 15:46:09 -07001331 ScopedJniThreadState ts(env);
Elliott Hughes885c3bd2011-08-22 16:59:20 -07001332 Object* o = Decode<Object*>(ts, java_object);
1333 Object* v = Decode<Object*>(ts, java_value);
1334 Field* f = DecodeField(ts, fid);
1335 f->SetObject(o, v);
Elliott Hughescdf53122011-08-19 15:46:09 -07001336 }
1337
Elliott Hughes885c3bd2011-08-22 16:59:20 -07001338 static void SetStaticObjectField(JNIEnv* env, jclass, jfieldID fid, jobject java_value) {
Elliott Hughescdf53122011-08-19 15:46:09 -07001339 ScopedJniThreadState ts(env);
Elliott Hughes885c3bd2011-08-22 16:59:20 -07001340 Object* v = Decode<Object*>(ts, java_value);
1341 Field* f = DecodeField(ts, fid);
1342 f->SetObject(NULL, v);
Elliott Hughescdf53122011-08-19 15:46:09 -07001343 }
1344
Elliott Hughes885c3bd2011-08-22 16:59:20 -07001345#define GET_PRIMITIVE_FIELD(fn, instance) \
1346 ScopedJniThreadState ts(env); \
1347 Object* o = Decode<Object*>(ts, instance); \
1348 Field* f = DecodeField(ts, fid); \
1349 return f->fn(o)
1350
1351#define SET_PRIMITIVE_FIELD(fn, instance, value) \
1352 ScopedJniThreadState ts(env); \
1353 Object* o = Decode<Object*>(ts, instance); \
1354 Field* f = DecodeField(ts, fid); \
1355 f->fn(o, value)
1356
1357 static jboolean GetBooleanField(JNIEnv* env, jobject obj, jfieldID fid) {
1358 GET_PRIMITIVE_FIELD(GetBoolean, obj);
Elliott Hughescdf53122011-08-19 15:46:09 -07001359 }
1360
Elliott Hughes885c3bd2011-08-22 16:59:20 -07001361 static jbyte GetByteField(JNIEnv* env, jobject obj, jfieldID fid) {
1362 GET_PRIMITIVE_FIELD(GetByte, obj);
Elliott Hughescdf53122011-08-19 15:46:09 -07001363 }
1364
Elliott Hughes885c3bd2011-08-22 16:59:20 -07001365 static jchar GetCharField(JNIEnv* env, jobject obj, jfieldID fid) {
1366 GET_PRIMITIVE_FIELD(GetChar, obj);
Elliott Hughescdf53122011-08-19 15:46:09 -07001367 }
1368
Elliott Hughes885c3bd2011-08-22 16:59:20 -07001369 static jshort GetShortField(JNIEnv* env, jobject obj, jfieldID fid) {
1370 GET_PRIMITIVE_FIELD(GetShort, obj);
Elliott Hughescdf53122011-08-19 15:46:09 -07001371 }
1372
Elliott Hughes885c3bd2011-08-22 16:59:20 -07001373 static jint GetIntField(JNIEnv* env, jobject obj, jfieldID fid) {
1374 GET_PRIMITIVE_FIELD(GetInt, obj);
Elliott Hughescdf53122011-08-19 15:46:09 -07001375 }
1376
Elliott Hughes885c3bd2011-08-22 16:59:20 -07001377 static jlong GetLongField(JNIEnv* env, jobject obj, jfieldID fid) {
1378 GET_PRIMITIVE_FIELD(GetLong, obj);
Elliott Hughescdf53122011-08-19 15:46:09 -07001379 }
1380
Elliott Hughes885c3bd2011-08-22 16:59:20 -07001381 static jfloat GetFloatField(JNIEnv* env, jobject obj, jfieldID fid) {
1382 GET_PRIMITIVE_FIELD(GetFloat, obj);
Elliott Hughescdf53122011-08-19 15:46:09 -07001383 }
1384
Elliott Hughes885c3bd2011-08-22 16:59:20 -07001385 static jdouble GetDoubleField(JNIEnv* env, jobject obj, jfieldID fid) {
1386 GET_PRIMITIVE_FIELD(GetDouble, obj);
Elliott Hughescdf53122011-08-19 15:46:09 -07001387 }
1388
Elliott Hughes885c3bd2011-08-22 16:59:20 -07001389 static jboolean GetStaticBooleanField(JNIEnv* env, jclass clazz, jfieldID fid) {
1390 GET_PRIMITIVE_FIELD(GetBoolean, NULL);
Elliott Hughescdf53122011-08-19 15:46:09 -07001391 }
1392
Elliott Hughes885c3bd2011-08-22 16:59:20 -07001393 static jbyte GetStaticByteField(JNIEnv* env, jclass clazz, jfieldID fid) {
1394 GET_PRIMITIVE_FIELD(GetByte, NULL);
Elliott Hughescdf53122011-08-19 15:46:09 -07001395 }
1396
Elliott Hughes885c3bd2011-08-22 16:59:20 -07001397 static jchar GetStaticCharField(JNIEnv* env, jclass clazz, jfieldID fid) {
1398 GET_PRIMITIVE_FIELD(GetChar, NULL);
Elliott Hughescdf53122011-08-19 15:46:09 -07001399 }
1400
Elliott Hughes885c3bd2011-08-22 16:59:20 -07001401 static jshort GetStaticShortField(JNIEnv* env, jclass clazz, jfieldID fid) {
1402 GET_PRIMITIVE_FIELD(GetShort, NULL);
Elliott Hughescdf53122011-08-19 15:46:09 -07001403 }
1404
Elliott Hughes885c3bd2011-08-22 16:59:20 -07001405 static jint GetStaticIntField(JNIEnv* env, jclass clazz, jfieldID fid) {
1406 GET_PRIMITIVE_FIELD(GetInt, NULL);
Elliott Hughescdf53122011-08-19 15:46:09 -07001407 }
1408
Elliott Hughes885c3bd2011-08-22 16:59:20 -07001409 static jlong GetStaticLongField(JNIEnv* env, jclass clazz, jfieldID fid) {
1410 GET_PRIMITIVE_FIELD(GetLong, NULL);
1411 }
1412
1413 static jfloat GetStaticFloatField(JNIEnv* env, jclass clazz, jfieldID fid) {
1414 GET_PRIMITIVE_FIELD(GetFloat, NULL);
1415 }
1416
1417 static jdouble GetStaticDoubleField(JNIEnv* env, jclass clazz, jfieldID fid) {
1418 GET_PRIMITIVE_FIELD(GetDouble, NULL);
1419 }
1420
1421 static void SetBooleanField(JNIEnv* env, jobject obj, jfieldID fid, jboolean v) {
1422 SET_PRIMITIVE_FIELD(SetBoolean, obj, v);
1423 }
1424
1425 static void SetByteField(JNIEnv* env, jobject obj, jfieldID fid, jbyte v) {
1426 SET_PRIMITIVE_FIELD(SetByte, obj, v);
1427 }
1428
1429 static void SetCharField(JNIEnv* env, jobject obj, jfieldID fid, jchar v) {
1430 SET_PRIMITIVE_FIELD(SetChar, obj, v);
1431 }
1432
1433 static void SetFloatField(JNIEnv* env, jobject obj, jfieldID fid, jfloat v) {
1434 SET_PRIMITIVE_FIELD(SetFloat, obj, v);
1435 }
1436
1437 static void SetDoubleField(JNIEnv* env, jobject obj, jfieldID fid, jdouble v) {
1438 SET_PRIMITIVE_FIELD(SetDouble, obj, v);
1439 }
1440
1441 static void SetIntField(JNIEnv* env, jobject obj, jfieldID fid, jint v) {
1442 SET_PRIMITIVE_FIELD(SetInt, obj, v);
1443 }
1444
1445 static void SetLongField(JNIEnv* env, jobject obj, jfieldID fid, jlong v) {
1446 SET_PRIMITIVE_FIELD(SetLong, obj, v);
1447 }
1448
1449 static void SetShortField(JNIEnv* env, jobject obj, jfieldID fid, jshort v) {
1450 SET_PRIMITIVE_FIELD(SetShort, obj, v);
1451 }
1452
1453 static void SetStaticBooleanField(JNIEnv* env, jclass, jfieldID fid, jboolean v) {
1454 SET_PRIMITIVE_FIELD(SetBoolean, NULL, v);
1455 }
1456
1457 static void SetStaticByteField(JNIEnv* env, jclass, jfieldID fid, jbyte v) {
1458 SET_PRIMITIVE_FIELD(SetByte, NULL, v);
1459 }
1460
1461 static void SetStaticCharField(JNIEnv* env, jclass, jfieldID fid, jchar v) {
1462 SET_PRIMITIVE_FIELD(SetChar, NULL, v);
1463 }
1464
1465 static void SetStaticFloatField(JNIEnv* env, jclass, jfieldID fid, jfloat v) {
1466 SET_PRIMITIVE_FIELD(SetFloat, NULL, v);
1467 }
1468
1469 static void SetStaticDoubleField(JNIEnv* env, jclass, jfieldID fid, jdouble v) {
1470 SET_PRIMITIVE_FIELD(SetDouble, NULL, v);
1471 }
1472
1473 static void SetStaticIntField(JNIEnv* env, jclass, jfieldID fid, jint v) {
1474 SET_PRIMITIVE_FIELD(SetInt, NULL, v);
1475 }
1476
1477 static void SetStaticLongField(JNIEnv* env, jclass, jfieldID fid, jlong v) {
1478 SET_PRIMITIVE_FIELD(SetLong, NULL, v);
1479 }
1480
1481 static void SetStaticShortField(JNIEnv* env, jclass, jfieldID fid, jshort v) {
1482 SET_PRIMITIVE_FIELD(SetShort, NULL, v);
Elliott Hughescdf53122011-08-19 15:46:09 -07001483 }
1484
1485 static jobject CallStaticObjectMethod(JNIEnv* env,
1486 jclass clazz, jmethodID methodID, ...) {
1487 ScopedJniThreadState ts(env);
1488 va_list ap;
1489 va_start(ap, methodID);
1490 JValue result = InvokeWithVarArgs(ts, NULL, methodID, ap);
1491 jobject local_result = AddLocalReference<jobject>(ts, result.l);
1492 va_end(ap);
1493 return local_result;
1494 }
1495
1496 static jobject CallStaticObjectMethodV(JNIEnv* env,
1497 jclass clazz, jmethodID methodID, va_list args) {
1498 ScopedJniThreadState ts(env);
1499 JValue result = InvokeWithVarArgs(ts, NULL, methodID, args);
1500 return AddLocalReference<jobject>(ts, result.l);
1501 }
1502
1503 static jobject CallStaticObjectMethodA(JNIEnv* env,
1504 jclass clazz, jmethodID methodID, jvalue* args) {
1505 ScopedJniThreadState ts(env);
1506 JValue result = InvokeWithJValues(ts, NULL, methodID, args);
1507 return AddLocalReference<jobject>(ts, result.l);
1508 }
1509
1510 static jboolean CallStaticBooleanMethod(JNIEnv* env,
1511 jclass clazz, jmethodID methodID, ...) {
1512 ScopedJniThreadState ts(env);
1513 va_list ap;
1514 va_start(ap, methodID);
1515 JValue result = InvokeWithVarArgs(ts, NULL, methodID, ap);
1516 va_end(ap);
1517 return result.z;
1518 }
1519
1520 static jboolean CallStaticBooleanMethodV(JNIEnv* env,
1521 jclass clazz, jmethodID methodID, va_list args) {
1522 ScopedJniThreadState ts(env);
1523 return InvokeWithVarArgs(ts, NULL, methodID, args).z;
1524 }
1525
1526 static jboolean CallStaticBooleanMethodA(JNIEnv* env,
1527 jclass clazz, jmethodID methodID, jvalue* args) {
1528 ScopedJniThreadState ts(env);
1529 return InvokeWithJValues(ts, NULL, methodID, args).z;
1530 }
1531
1532 static jbyte CallStaticByteMethod(JNIEnv* env, jclass clazz, jmethodID methodID, ...) {
1533 ScopedJniThreadState ts(env);
1534 va_list ap;
1535 va_start(ap, methodID);
1536 JValue result = InvokeWithVarArgs(ts, NULL, methodID, ap);
1537 va_end(ap);
1538 return result.b;
1539 }
1540
1541 static jbyte CallStaticByteMethodV(JNIEnv* env,
1542 jclass clazz, jmethodID methodID, va_list args) {
1543 ScopedJniThreadState ts(env);
1544 return InvokeWithVarArgs(ts, NULL, methodID, args).b;
1545 }
1546
1547 static jbyte CallStaticByteMethodA(JNIEnv* env,
1548 jclass clazz, jmethodID methodID, jvalue* args) {
1549 ScopedJniThreadState ts(env);
1550 return InvokeWithJValues(ts, NULL, methodID, args).b;
1551 }
1552
1553 static jchar CallStaticCharMethod(JNIEnv* env, jclass clazz, jmethodID methodID, ...) {
1554 ScopedJniThreadState ts(env);
1555 va_list ap;
1556 va_start(ap, methodID);
1557 JValue result = InvokeWithVarArgs(ts, NULL, methodID, ap);
1558 va_end(ap);
1559 return result.c;
1560 }
1561
1562 static jchar CallStaticCharMethodV(JNIEnv* env,
1563 jclass clazz, jmethodID methodID, va_list args) {
1564 ScopedJniThreadState ts(env);
1565 return InvokeWithVarArgs(ts, NULL, methodID, args).c;
1566 }
1567
1568 static jchar CallStaticCharMethodA(JNIEnv* env,
1569 jclass clazz, jmethodID methodID, jvalue* args) {
1570 ScopedJniThreadState ts(env);
1571 return InvokeWithJValues(ts, NULL, methodID, args).c;
1572 }
1573
1574 static jshort CallStaticShortMethod(JNIEnv* env, jclass clazz, jmethodID methodID, ...) {
1575 ScopedJniThreadState ts(env);
1576 va_list ap;
1577 va_start(ap, methodID);
1578 JValue result = InvokeWithVarArgs(ts, NULL, methodID, ap);
1579 va_end(ap);
1580 return result.s;
1581 }
1582
1583 static jshort CallStaticShortMethodV(JNIEnv* env,
1584 jclass clazz, jmethodID methodID, va_list args) {
1585 ScopedJniThreadState ts(env);
1586 return InvokeWithVarArgs(ts, NULL, methodID, args).s;
1587 }
1588
1589 static jshort CallStaticShortMethodA(JNIEnv* env,
1590 jclass clazz, jmethodID methodID, jvalue* args) {
1591 ScopedJniThreadState ts(env);
1592 return InvokeWithJValues(ts, NULL, methodID, args).s;
1593 }
1594
1595 static jint CallStaticIntMethod(JNIEnv* env, jclass clazz, jmethodID methodID, ...) {
1596 ScopedJniThreadState ts(env);
1597 va_list ap;
1598 va_start(ap, methodID);
1599 JValue result = InvokeWithVarArgs(ts, NULL, methodID, ap);
1600 va_end(ap);
1601 return result.i;
1602 }
1603
1604 static jint CallStaticIntMethodV(JNIEnv* env,
1605 jclass clazz, jmethodID methodID, va_list args) {
1606 ScopedJniThreadState ts(env);
1607 return InvokeWithVarArgs(ts, NULL, methodID, args).i;
1608 }
1609
1610 static jint CallStaticIntMethodA(JNIEnv* env,
1611 jclass clazz, jmethodID methodID, jvalue* args) {
1612 ScopedJniThreadState ts(env);
1613 return InvokeWithJValues(ts, NULL, methodID, args).i;
1614 }
1615
1616 static jlong CallStaticLongMethod(JNIEnv* env, jclass clazz, jmethodID methodID, ...) {
1617 ScopedJniThreadState ts(env);
1618 va_list ap;
1619 va_start(ap, methodID);
1620 JValue result = InvokeWithVarArgs(ts, NULL, methodID, ap);
1621 va_end(ap);
1622 return result.j;
1623 }
1624
1625 static jlong CallStaticLongMethodV(JNIEnv* env,
1626 jclass clazz, jmethodID methodID, va_list args) {
1627 ScopedJniThreadState ts(env);
1628 return InvokeWithVarArgs(ts, NULL, methodID, args).j;
1629 }
1630
1631 static jlong CallStaticLongMethodA(JNIEnv* env,
1632 jclass clazz, jmethodID methodID, jvalue* args) {
1633 ScopedJniThreadState ts(env);
1634 return InvokeWithJValues(ts, NULL, methodID, args).j;
1635 }
1636
1637 static jfloat CallStaticFloatMethod(JNIEnv* env, jclass cls, jmethodID methodID, ...) {
1638 ScopedJniThreadState ts(env);
1639 va_list ap;
1640 va_start(ap, methodID);
1641 JValue result = InvokeWithVarArgs(ts, NULL, methodID, ap);
1642 va_end(ap);
1643 return result.f;
1644 }
1645
1646 static jfloat CallStaticFloatMethodV(JNIEnv* env,
1647 jclass clazz, jmethodID methodID, va_list args) {
1648 ScopedJniThreadState ts(env);
1649 return InvokeWithVarArgs(ts, NULL, methodID, args).f;
1650 }
1651
1652 static jfloat CallStaticFloatMethodA(JNIEnv* env,
1653 jclass clazz, jmethodID methodID, jvalue* args) {
1654 ScopedJniThreadState ts(env);
1655 return InvokeWithJValues(ts, NULL, methodID, args).f;
1656 }
1657
1658 static jdouble CallStaticDoubleMethod(JNIEnv* env, jclass cls, jmethodID methodID, ...) {
1659 ScopedJniThreadState ts(env);
1660 va_list ap;
1661 va_start(ap, methodID);
1662 JValue result = InvokeWithVarArgs(ts, NULL, methodID, ap);
1663 va_end(ap);
1664 return result.d;
1665 }
1666
1667 static jdouble CallStaticDoubleMethodV(JNIEnv* env,
1668 jclass clazz, jmethodID methodID, va_list args) {
1669 ScopedJniThreadState ts(env);
1670 return InvokeWithVarArgs(ts, NULL, methodID, args).d;
1671 }
1672
1673 static jdouble CallStaticDoubleMethodA(JNIEnv* env,
1674 jclass clazz, jmethodID methodID, jvalue* args) {
1675 ScopedJniThreadState ts(env);
1676 return InvokeWithJValues(ts, NULL, methodID, args).d;
1677 }
1678
1679 static void CallStaticVoidMethod(JNIEnv* env, jclass cls, jmethodID methodID, ...) {
1680 ScopedJniThreadState ts(env);
1681 va_list ap;
1682 va_start(ap, methodID);
1683 InvokeWithVarArgs(ts, NULL, methodID, ap);
1684 va_end(ap);
1685 }
1686
1687 static void CallStaticVoidMethodV(JNIEnv* env,
1688 jclass cls, jmethodID methodID, va_list args) {
1689 ScopedJniThreadState ts(env);
1690 InvokeWithVarArgs(ts, NULL, methodID, args);
1691 }
1692
1693 static void CallStaticVoidMethodA(JNIEnv* env,
1694 jclass cls, jmethodID methodID, jvalue* args) {
1695 ScopedJniThreadState ts(env);
1696 InvokeWithJValues(ts, NULL, methodID, args);
1697 }
1698
Elliott Hughes814e4032011-08-23 12:07:56 -07001699 static jstring NewString(JNIEnv* env, const jchar* chars, jsize char_count) {
Elliott Hughescdf53122011-08-19 15:46:09 -07001700 ScopedJniThreadState ts(env);
Elliott Hughes814e4032011-08-23 12:07:56 -07001701 if (chars == NULL && char_count == 0) {
1702 return NULL;
1703 }
1704 String* result = String::AllocFromUtf16(char_count, chars);
1705 return AddLocalReference<jstring>(ts, result);
Elliott Hughescdf53122011-08-19 15:46:09 -07001706 }
1707
1708 static jstring NewStringUTF(JNIEnv* env, const char* utf) {
1709 ScopedJniThreadState ts(env);
1710 if (utf == NULL) {
1711 return NULL;
1712 }
1713 String* result = String::AllocFromModifiedUtf8(utf);
1714 return AddLocalReference<jstring>(ts, result);
1715 }
1716
Elliott Hughes814e4032011-08-23 12:07:56 -07001717 static jsize GetStringLength(JNIEnv* env, jstring java_string) {
1718 ScopedJniThreadState ts(env);
1719 return Decode<String*>(ts, java_string)->GetLength();
1720 }
1721
1722 static jsize GetStringUTFLength(JNIEnv* env, jstring java_string) {
1723 ScopedJniThreadState ts(env);
1724 return Decode<String*>(ts, java_string)->GetUtfLength();
1725 }
1726
1727 static void GetStringRegion(JNIEnv* env, jstring str, jsize start, jsize len, jchar* buf) {
Elliott Hughescdf53122011-08-19 15:46:09 -07001728 ScopedJniThreadState ts(env);
1729 UNIMPLEMENTED(FATAL);
Elliott Hughes814e4032011-08-23 12:07:56 -07001730 }
1731
1732 static void GetStringUTFRegion(JNIEnv* env, jstring str, jsize start, jsize len, char* buf) {
1733 ScopedJniThreadState ts(env);
1734 UNIMPLEMENTED(FATAL);
1735 }
1736
1737 static const jchar* GetStringChars(JNIEnv* env, jstring str, jboolean* isCopy) {
1738 ScopedJniThreadState ts(env);
1739 UNIMPLEMENTED(FATAL);
1740 return NULL;
1741 }
1742
1743 static void ReleaseStringChars(JNIEnv* env, jstring str, const jchar* chars) {
1744 ScopedJniThreadState ts(env);
1745 UNIMPLEMENTED(FATAL);
Elliott Hughescdf53122011-08-19 15:46:09 -07001746 }
1747
1748 static const char* GetStringUTFChars(JNIEnv* env, jstring str, jboolean* isCopy) {
1749 ScopedJniThreadState ts(env);
1750 UNIMPLEMENTED(FATAL);
1751 return NULL;
1752 }
1753
1754 static void ReleaseStringUTFChars(JNIEnv* env, jstring str, const char* chars) {
1755 ScopedJniThreadState ts(env);
1756 UNIMPLEMENTED(FATAL);
1757 }
1758
Elliott Hughesbd935992011-08-22 11:59:34 -07001759 static jsize GetArrayLength(JNIEnv* env, jarray java_array) {
Elliott Hughescdf53122011-08-19 15:46:09 -07001760 ScopedJniThreadState ts(env);
Elliott Hughesbd935992011-08-22 11:59:34 -07001761 Object* obj = Decode<Object*>(ts, java_array);
1762 CHECK(obj->IsArray()); // TODO: ReportJniError
1763 Array* array = obj->AsArray();
1764 return array->GetLength();
Elliott Hughescdf53122011-08-19 15:46:09 -07001765 }
1766
Elliott Hughes814e4032011-08-23 12:07:56 -07001767 static jobject GetObjectArrayElement(JNIEnv* env, jobjectArray java_array, jsize index) {
Elliott Hughescdf53122011-08-19 15:46:09 -07001768 ScopedJniThreadState ts(env);
Elliott Hughes814e4032011-08-23 12:07:56 -07001769 ObjectArray<Object>* array = Decode<ObjectArray<Object>*>(ts, java_array);
1770 return AddLocalReference<jobject>(ts, array->Get(index));
Elliott Hughescdf53122011-08-19 15:46:09 -07001771 }
1772
1773 static void SetObjectArrayElement(JNIEnv* env,
1774 jobjectArray java_array, jsize index, jobject java_value) {
1775 ScopedJniThreadState ts(env);
1776 ObjectArray<Object>* array = Decode<ObjectArray<Object>*>(ts, java_array);
1777 Object* value = Decode<Object*>(ts, java_value);
1778 array->Set(index, value);
1779 }
1780
1781 static jbooleanArray NewBooleanArray(JNIEnv* env, jsize length) {
1782 ScopedJniThreadState ts(env);
1783 return NewPrimitiveArray<jbooleanArray, BooleanArray>(ts, length);
1784 }
1785
1786 static jbyteArray NewByteArray(JNIEnv* env, jsize length) {
1787 ScopedJniThreadState ts(env);
1788 return NewPrimitiveArray<jbyteArray, ByteArray>(ts, length);
1789 }
1790
1791 static jcharArray NewCharArray(JNIEnv* env, jsize length) {
1792 ScopedJniThreadState ts(env);
1793 return NewPrimitiveArray<jcharArray, CharArray>(ts, length);
1794 }
1795
1796 static jdoubleArray NewDoubleArray(JNIEnv* env, jsize length) {
1797 ScopedJniThreadState ts(env);
1798 return NewPrimitiveArray<jdoubleArray, DoubleArray>(ts, length);
1799 }
1800
1801 static jfloatArray NewFloatArray(JNIEnv* env, jsize length) {
1802 ScopedJniThreadState ts(env);
1803 return NewPrimitiveArray<jfloatArray, FloatArray>(ts, length);
1804 }
1805
1806 static jintArray NewIntArray(JNIEnv* env, jsize length) {
1807 ScopedJniThreadState ts(env);
1808 return NewPrimitiveArray<jintArray, IntArray>(ts, length);
1809 }
1810
1811 static jlongArray NewLongArray(JNIEnv* env, jsize length) {
1812 ScopedJniThreadState ts(env);
1813 return NewPrimitiveArray<jlongArray, LongArray>(ts, length);
1814 }
1815
1816 static jobjectArray NewObjectArray(JNIEnv* env, jsize length, jclass element_jclass, jobject initial_element) {
1817 ScopedJniThreadState ts(env);
1818 CHECK_GE(length, 0); // TODO: ReportJniError
1819
1820 // Compute the array class corresponding to the given element class.
1821 Class* element_class = Decode<Class*>(ts, element_jclass);
1822 std::string descriptor;
1823 descriptor += "[";
Brian Carlstrom9cff8e12011-08-18 16:47:29 -07001824 descriptor += element_class->GetDescriptor()->ToModifiedUtf8();
Elliott Hughescdf53122011-08-19 15:46:09 -07001825
1826 // Find the class.
1827 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
1828 // TODO: need to get the appropriate ClassLoader.
1829 Class* array_class = class_linker->FindClass(descriptor, NULL);
1830 if (array_class == NULL) {
1831 return NULL;
1832 }
1833
1834 ObjectArray<Object>* result = ObjectArray<Object>::Alloc(array_class, length);
1835 CHECK(initial_element == NULL); // TODO: support initial_element
1836 return AddLocalReference<jobjectArray>(ts, result);
1837 }
1838
1839 static jshortArray NewShortArray(JNIEnv* env, jsize length) {
1840 ScopedJniThreadState ts(env);
1841 return NewPrimitiveArray<jshortArray, ShortArray>(ts, length);
1842 }
1843
1844 static jboolean* GetBooleanArrayElements(JNIEnv* env,
1845 jbooleanArray array, jboolean* isCopy) {
1846 ScopedJniThreadState ts(env);
1847 UNIMPLEMENTED(FATAL);
1848 return NULL;
1849 }
1850
1851 static jbyte* GetByteArrayElements(JNIEnv* env, jbyteArray array, jboolean* isCopy) {
1852 ScopedJniThreadState ts(env);
1853 UNIMPLEMENTED(FATAL);
1854 return NULL;
1855 }
1856
1857 static jchar* GetCharArrayElements(JNIEnv* env, jcharArray array, jboolean* isCopy) {
1858 ScopedJniThreadState ts(env);
1859 UNIMPLEMENTED(FATAL);
1860 return NULL;
1861 }
1862
1863 static jshort* GetShortArrayElements(JNIEnv* env,
1864 jshortArray array, jboolean* isCopy) {
1865 ScopedJniThreadState ts(env);
1866 UNIMPLEMENTED(FATAL);
1867 return NULL;
1868 }
1869
1870 static jint* GetIntArrayElements(JNIEnv* env, jintArray array, jboolean* isCopy) {
1871 ScopedJniThreadState ts(env);
1872 UNIMPLEMENTED(FATAL);
1873 return NULL;
1874 }
1875
1876 static jlong* GetLongArrayElements(JNIEnv* env, jlongArray array, jboolean* isCopy) {
1877 ScopedJniThreadState ts(env);
1878 UNIMPLEMENTED(FATAL);
1879 return NULL;
1880 }
1881
1882 static jfloat* GetFloatArrayElements(JNIEnv* env,
1883 jfloatArray array, jboolean* isCopy) {
1884 ScopedJniThreadState ts(env);
1885 UNIMPLEMENTED(FATAL);
1886 return NULL;
1887 }
1888
1889 static jdouble* GetDoubleArrayElements(JNIEnv* env,
1890 jdoubleArray array, jboolean* isCopy) {
1891 ScopedJniThreadState ts(env);
1892 UNIMPLEMENTED(FATAL);
1893 return NULL;
1894 }
1895
1896 static void ReleaseBooleanArrayElements(JNIEnv* env,
1897 jbooleanArray array, jboolean* elems, jint mode) {
1898 ScopedJniThreadState ts(env);
1899 UNIMPLEMENTED(FATAL);
1900 }
1901
1902 static void ReleaseByteArrayElements(JNIEnv* env,
1903 jbyteArray array, jbyte* elems, jint mode) {
1904 ScopedJniThreadState ts(env);
1905 UNIMPLEMENTED(FATAL);
1906 }
1907
1908 static void ReleaseCharArrayElements(JNIEnv* env,
1909 jcharArray array, jchar* elems, jint mode) {
1910 ScopedJniThreadState ts(env);
1911 UNIMPLEMENTED(FATAL);
1912 }
1913
1914 static void ReleaseShortArrayElements(JNIEnv* env,
1915 jshortArray array, jshort* elems, jint mode) {
1916 ScopedJniThreadState ts(env);
1917 UNIMPLEMENTED(FATAL);
1918 }
1919
1920 static void ReleaseIntArrayElements(JNIEnv* env,
1921 jintArray array, jint* elems, jint mode) {
1922 ScopedJniThreadState ts(env);
1923 UNIMPLEMENTED(FATAL);
1924 }
1925
1926 static void ReleaseLongArrayElements(JNIEnv* env,
1927 jlongArray array, jlong* elems, jint mode) {
1928 ScopedJniThreadState ts(env);
1929 UNIMPLEMENTED(FATAL);
1930 }
1931
1932 static void ReleaseFloatArrayElements(JNIEnv* env,
1933 jfloatArray array, jfloat* elems, jint mode) {
1934 ScopedJniThreadState ts(env);
1935 UNIMPLEMENTED(FATAL);
1936 }
1937
1938 static void ReleaseDoubleArrayElements(JNIEnv* env,
1939 jdoubleArray array, jdouble* elems, jint mode) {
1940 ScopedJniThreadState ts(env);
1941 UNIMPLEMENTED(FATAL);
1942 }
1943
Elliott Hughes814e4032011-08-23 12:07:56 -07001944 static void GetBooleanArrayRegion(JNIEnv* env, jbooleanArray array, jsize start, jsize length, jboolean* buf) {
Elliott Hughescdf53122011-08-19 15:46:09 -07001945 ScopedJniThreadState ts(env);
Elliott Hughes814e4032011-08-23 12:07:56 -07001946 GetPrimitiveArrayRegion<jbooleanArray, jboolean, BooleanArray>(ts, array, start, length, buf);
Elliott Hughescdf53122011-08-19 15:46:09 -07001947 }
1948
Elliott Hughes814e4032011-08-23 12:07:56 -07001949 static void GetByteArrayRegion(JNIEnv* env, jbyteArray array, jsize start, jsize length, jbyte* buf) {
Elliott Hughescdf53122011-08-19 15:46:09 -07001950 ScopedJniThreadState ts(env);
Elliott Hughes814e4032011-08-23 12:07:56 -07001951 GetPrimitiveArrayRegion<jbyteArray, jbyte, ByteArray>(ts, array, start, length, buf);
Elliott Hughescdf53122011-08-19 15:46:09 -07001952 }
1953
Elliott Hughes814e4032011-08-23 12:07:56 -07001954 static void GetCharArrayRegion(JNIEnv* env, jcharArray array, jsize start, jsize length, jchar* buf) {
Elliott Hughescdf53122011-08-19 15:46:09 -07001955 ScopedJniThreadState ts(env);
Elliott Hughes814e4032011-08-23 12:07:56 -07001956 GetPrimitiveArrayRegion<jcharArray, jchar, CharArray>(ts, array, start, length, buf);
Elliott Hughescdf53122011-08-19 15:46:09 -07001957 }
1958
Elliott Hughes814e4032011-08-23 12:07:56 -07001959 static void GetDoubleArrayRegion(JNIEnv* env, jdoubleArray array, jsize start, jsize length, jdouble* buf) {
Elliott Hughescdf53122011-08-19 15:46:09 -07001960 ScopedJniThreadState ts(env);
Elliott Hughes814e4032011-08-23 12:07:56 -07001961 GetPrimitiveArrayRegion<jdoubleArray, jdouble, DoubleArray>(ts, array, start, length, buf);
Elliott Hughescdf53122011-08-19 15:46:09 -07001962 }
1963
Elliott Hughes814e4032011-08-23 12:07:56 -07001964 static void GetFloatArrayRegion(JNIEnv* env, jfloatArray array, jsize start, jsize length, jfloat* buf) {
Elliott Hughescdf53122011-08-19 15:46:09 -07001965 ScopedJniThreadState ts(env);
Elliott Hughes814e4032011-08-23 12:07:56 -07001966 GetPrimitiveArrayRegion<jfloatArray, jfloat, FloatArray>(ts, array, start, length, buf);
Elliott Hughescdf53122011-08-19 15:46:09 -07001967 }
1968
Elliott Hughes814e4032011-08-23 12:07:56 -07001969 static void GetIntArrayRegion(JNIEnv* env, jintArray array, jsize start, jsize length, jint* buf) {
Elliott Hughescdf53122011-08-19 15:46:09 -07001970 ScopedJniThreadState ts(env);
Elliott Hughes814e4032011-08-23 12:07:56 -07001971 GetPrimitiveArrayRegion<jintArray, jint, IntArray>(ts, array, start, length, buf);
Elliott Hughescdf53122011-08-19 15:46:09 -07001972 }
1973
Elliott Hughes814e4032011-08-23 12:07:56 -07001974 static void GetLongArrayRegion(JNIEnv* env, jlongArray array, jsize start, jsize length, jlong* buf) {
Elliott Hughescdf53122011-08-19 15:46:09 -07001975 ScopedJniThreadState ts(env);
Elliott Hughes814e4032011-08-23 12:07:56 -07001976 GetPrimitiveArrayRegion<jlongArray, jlong, LongArray>(ts, array, start, length, buf);
Elliott Hughescdf53122011-08-19 15:46:09 -07001977 }
1978
Elliott Hughes814e4032011-08-23 12:07:56 -07001979 static void GetShortArrayRegion(JNIEnv* env, jshortArray array, jsize start, jsize length, jshort* buf) {
Elliott Hughescdf53122011-08-19 15:46:09 -07001980 ScopedJniThreadState ts(env);
Elliott Hughes814e4032011-08-23 12:07:56 -07001981 GetPrimitiveArrayRegion<jshortArray, jshort, ShortArray>(ts, array, start, length, buf);
Elliott Hughescdf53122011-08-19 15:46:09 -07001982 }
1983
Elliott Hughes814e4032011-08-23 12:07:56 -07001984 static void SetBooleanArrayRegion(JNIEnv* env, jbooleanArray array, jsize start, jsize length, const jboolean* buf) {
Elliott Hughescdf53122011-08-19 15:46:09 -07001985 ScopedJniThreadState ts(env);
Elliott Hughes814e4032011-08-23 12:07:56 -07001986 SetPrimitiveArrayRegion<jbooleanArray, jboolean, BooleanArray>(ts, array, start, length, buf);
Elliott Hughescdf53122011-08-19 15:46:09 -07001987 }
1988
Elliott Hughes814e4032011-08-23 12:07:56 -07001989 static void SetByteArrayRegion(JNIEnv* env, jbyteArray array, jsize start, jsize length, const jbyte* buf) {
Elliott Hughescdf53122011-08-19 15:46:09 -07001990 ScopedJniThreadState ts(env);
Elliott Hughes814e4032011-08-23 12:07:56 -07001991 SetPrimitiveArrayRegion<jbyteArray, jbyte, ByteArray>(ts, array, start, length, buf);
Elliott Hughescdf53122011-08-19 15:46:09 -07001992 }
1993
Elliott Hughes814e4032011-08-23 12:07:56 -07001994 static void SetCharArrayRegion(JNIEnv* env, jcharArray array, jsize start, jsize length, const jchar* buf) {
Elliott Hughescdf53122011-08-19 15:46:09 -07001995 ScopedJniThreadState ts(env);
Elliott Hughes814e4032011-08-23 12:07:56 -07001996 SetPrimitiveArrayRegion<jcharArray, jchar, CharArray>(ts, array, start, length, buf);
Elliott Hughescdf53122011-08-19 15:46:09 -07001997 }
1998
Elliott Hughes814e4032011-08-23 12:07:56 -07001999 static void SetDoubleArrayRegion(JNIEnv* env, jdoubleArray array, jsize start, jsize length, const jdouble* buf) {
Elliott Hughescdf53122011-08-19 15:46:09 -07002000 ScopedJniThreadState ts(env);
Elliott Hughes814e4032011-08-23 12:07:56 -07002001 SetPrimitiveArrayRegion<jdoubleArray, jdouble, DoubleArray>(ts, array, start, length, buf);
Elliott Hughescdf53122011-08-19 15:46:09 -07002002 }
2003
Elliott Hughes814e4032011-08-23 12:07:56 -07002004 static void SetFloatArrayRegion(JNIEnv* env, jfloatArray array, jsize start, jsize length, const jfloat* buf) {
Elliott Hughescdf53122011-08-19 15:46:09 -07002005 ScopedJniThreadState ts(env);
Elliott Hughes814e4032011-08-23 12:07:56 -07002006 SetPrimitiveArrayRegion<jfloatArray, jfloat, FloatArray>(ts, array, start, length, buf);
Elliott Hughescdf53122011-08-19 15:46:09 -07002007 }
2008
Elliott Hughes814e4032011-08-23 12:07:56 -07002009 static void SetIntArrayRegion(JNIEnv* env, jintArray array, jsize start, jsize length, const jint* buf) {
Elliott Hughescdf53122011-08-19 15:46:09 -07002010 ScopedJniThreadState ts(env);
Elliott Hughes814e4032011-08-23 12:07:56 -07002011 SetPrimitiveArrayRegion<jintArray, jint, IntArray>(ts, array, start, length, buf);
Elliott Hughescdf53122011-08-19 15:46:09 -07002012 }
2013
Elliott Hughes814e4032011-08-23 12:07:56 -07002014 static void SetLongArrayRegion(JNIEnv* env, jlongArray array, jsize start, jsize length, const jlong* buf) {
Elliott Hughescdf53122011-08-19 15:46:09 -07002015 ScopedJniThreadState ts(env);
Elliott Hughes814e4032011-08-23 12:07:56 -07002016 SetPrimitiveArrayRegion<jlongArray, jlong, LongArray>(ts, array, start, length, buf);
Elliott Hughescdf53122011-08-19 15:46:09 -07002017 }
2018
Elliott Hughes814e4032011-08-23 12:07:56 -07002019 static void SetShortArrayRegion(JNIEnv* env, jshortArray array, jsize start, jsize length, const jshort* buf) {
Elliott Hughescdf53122011-08-19 15:46:09 -07002020 ScopedJniThreadState ts(env);
Elliott Hughes814e4032011-08-23 12:07:56 -07002021 SetPrimitiveArrayRegion<jshortArray, jshort, ShortArray>(ts, array, start, length, buf);
Elliott Hughescdf53122011-08-19 15:46:09 -07002022 }
2023
2024 static jint RegisterNatives(JNIEnv* env,
2025 jclass clazz, const JNINativeMethod* methods, jint nMethods) {
2026 ScopedJniThreadState ts(env);
2027 Class* klass = Decode<Class*>(ts, clazz);
2028 for(int i = 0; i < nMethods; i++) {
2029 const char* name = methods[i].name;
2030 const char* sig = methods[i].signature;
2031
2032 if (*sig == '!') {
2033 // TODO: fast jni. it's too noisy to log all these.
2034 ++sig;
2035 }
2036
2037 Method* method = klass->FindDirectMethod(name, sig);
2038 if (method == NULL) {
2039 method = klass->FindVirtualMethod(name, sig);
2040 }
2041 if (method == NULL) {
2042 Thread* self = Thread::Current();
Elliott Hughese5b0dc82011-08-23 09:59:02 -07002043 std::string class_descriptor(klass->GetDescriptor()->ToModifiedUtf8());
Elliott Hughescdf53122011-08-19 15:46:09 -07002044 self->ThrowNewException("Ljava/lang/NoSuchMethodError;",
2045 "no method \"%s.%s%s\"",
Elliott Hughese5b0dc82011-08-23 09:59:02 -07002046 class_descriptor.c_str(), name, sig);
Elliott Hughescdf53122011-08-19 15:46:09 -07002047 return JNI_ERR;
2048 } else if (!method->IsNative()) {
2049 Thread* self = Thread::Current();
Elliott Hughese5b0dc82011-08-23 09:59:02 -07002050 std::string class_descriptor(klass->GetDescriptor()->ToModifiedUtf8());
Elliott Hughescdf53122011-08-19 15:46:09 -07002051 self->ThrowNewException("Ljava/lang/NoSuchMethodError;",
2052 "method \"%s.%s%s\" is not native",
Elliott Hughese5b0dc82011-08-23 09:59:02 -07002053 class_descriptor.c_str(), name, sig);
Elliott Hughescdf53122011-08-19 15:46:09 -07002054 return JNI_ERR;
2055 }
2056 method->RegisterNative(methods[i].fnPtr);
2057 }
2058 return JNI_OK;
2059 }
2060
2061 static jint UnregisterNatives(JNIEnv* env, jclass clazz) {
2062 ScopedJniThreadState ts(env);
2063 UNIMPLEMENTED(FATAL);
2064 return 0;
2065 }
2066
2067 static jint MonitorEnter(JNIEnv* env, jobject obj) {
2068 ScopedJniThreadState ts(env);
2069 UNIMPLEMENTED(WARNING);
2070 return 0;
2071 }
2072
2073 static jint MonitorExit(JNIEnv* env, jobject obj) {
2074 ScopedJniThreadState ts(env);
2075 UNIMPLEMENTED(WARNING);
2076 return 0;
2077 }
2078
2079 static jint GetJavaVM(JNIEnv* env, JavaVM** vm) {
2080 ScopedJniThreadState ts(env);
2081 Runtime* runtime = Runtime::Current();
2082 if (runtime != NULL) {
2083 *vm = reinterpret_cast<JavaVM*>(runtime->GetJavaVM());
2084 } else {
2085 *vm = NULL;
2086 }
2087 return (*vm != NULL) ? JNI_OK : JNI_ERR;
2088 }
2089
Elliott Hughescdf53122011-08-19 15:46:09 -07002090 static void* GetPrimitiveArrayCritical(JNIEnv* env,
2091 jarray array, jboolean* isCopy) {
2092 ScopedJniThreadState ts(env);
2093 UNIMPLEMENTED(FATAL);
2094 return NULL;
2095 }
2096
2097 static void ReleasePrimitiveArrayCritical(JNIEnv* env,
2098 jarray array, void* carray, jint mode) {
2099 ScopedJniThreadState ts(env);
2100 UNIMPLEMENTED(FATAL);
2101 }
2102
2103 static const jchar* GetStringCritical(JNIEnv* env, jstring s, jboolean* isCopy) {
2104 ScopedJniThreadState ts(env);
2105 UNIMPLEMENTED(FATAL);
2106 return NULL;
2107 }
2108
2109 static void ReleaseStringCritical(JNIEnv* env, jstring s, const jchar* cstr) {
2110 ScopedJniThreadState ts(env);
2111 UNIMPLEMENTED(FATAL);
2112 }
2113
Elliott Hughescdf53122011-08-19 15:46:09 -07002114 static jobject NewDirectByteBuffer(JNIEnv* env, void* address, jlong capacity) {
2115 ScopedJniThreadState ts(env);
2116 UNIMPLEMENTED(FATAL);
2117 return NULL;
2118 }
2119
2120 static void* GetDirectBufferAddress(JNIEnv* env, jobject buf) {
2121 ScopedJniThreadState ts(env);
2122 UNIMPLEMENTED(FATAL);
2123 return NULL;
2124 }
2125
2126 static jlong GetDirectBufferCapacity(JNIEnv* env, jobject buf) {
2127 ScopedJniThreadState ts(env);
2128 UNIMPLEMENTED(FATAL);
2129 return 0;
2130 }
2131
2132 static jobjectRefType GetObjectRefType(JNIEnv* env, jobject jobj) {
2133 ScopedJniThreadState ts(env);
2134 UNIMPLEMENTED(FATAL);
2135 return JNIInvalidRefType;
2136 }
2137};
Carl Shapiroea4dca82011-08-01 13:45:38 -07002138
Elliott Hughes40ef99e2011-08-11 17:44:34 -07002139static const struct JNINativeInterface gNativeInterface = {
Carl Shapiroea4dca82011-08-01 13:45:38 -07002140 NULL, // reserved0.
2141 NULL, // reserved1.
2142 NULL, // reserved2.
2143 NULL, // reserved3.
Elliott Hughescdf53122011-08-19 15:46:09 -07002144 JNI::GetVersion,
2145 JNI::DefineClass,
2146 JNI::FindClass,
2147 JNI::FromReflectedMethod,
2148 JNI::FromReflectedField,
2149 JNI::ToReflectedMethod,
2150 JNI::GetSuperclass,
2151 JNI::IsAssignableFrom,
2152 JNI::ToReflectedField,
2153 JNI::Throw,
2154 JNI::ThrowNew,
2155 JNI::ExceptionOccurred,
2156 JNI::ExceptionDescribe,
2157 JNI::ExceptionClear,
2158 JNI::FatalError,
2159 JNI::PushLocalFrame,
2160 JNI::PopLocalFrame,
2161 JNI::NewGlobalRef,
2162 JNI::DeleteGlobalRef,
2163 JNI::DeleteLocalRef,
2164 JNI::IsSameObject,
2165 JNI::NewLocalRef,
2166 JNI::EnsureLocalCapacity,
2167 JNI::AllocObject,
2168 JNI::NewObject,
2169 JNI::NewObjectV,
2170 JNI::NewObjectA,
2171 JNI::GetObjectClass,
2172 JNI::IsInstanceOf,
2173 JNI::GetMethodID,
2174 JNI::CallObjectMethod,
2175 JNI::CallObjectMethodV,
2176 JNI::CallObjectMethodA,
2177 JNI::CallBooleanMethod,
2178 JNI::CallBooleanMethodV,
2179 JNI::CallBooleanMethodA,
2180 JNI::CallByteMethod,
2181 JNI::CallByteMethodV,
2182 JNI::CallByteMethodA,
2183 JNI::CallCharMethod,
2184 JNI::CallCharMethodV,
2185 JNI::CallCharMethodA,
2186 JNI::CallShortMethod,
2187 JNI::CallShortMethodV,
2188 JNI::CallShortMethodA,
2189 JNI::CallIntMethod,
2190 JNI::CallIntMethodV,
2191 JNI::CallIntMethodA,
2192 JNI::CallLongMethod,
2193 JNI::CallLongMethodV,
2194 JNI::CallLongMethodA,
2195 JNI::CallFloatMethod,
2196 JNI::CallFloatMethodV,
2197 JNI::CallFloatMethodA,
2198 JNI::CallDoubleMethod,
2199 JNI::CallDoubleMethodV,
2200 JNI::CallDoubleMethodA,
2201 JNI::CallVoidMethod,
2202 JNI::CallVoidMethodV,
2203 JNI::CallVoidMethodA,
2204 JNI::CallNonvirtualObjectMethod,
2205 JNI::CallNonvirtualObjectMethodV,
2206 JNI::CallNonvirtualObjectMethodA,
2207 JNI::CallNonvirtualBooleanMethod,
2208 JNI::CallNonvirtualBooleanMethodV,
2209 JNI::CallNonvirtualBooleanMethodA,
2210 JNI::CallNonvirtualByteMethod,
2211 JNI::CallNonvirtualByteMethodV,
2212 JNI::CallNonvirtualByteMethodA,
2213 JNI::CallNonvirtualCharMethod,
2214 JNI::CallNonvirtualCharMethodV,
2215 JNI::CallNonvirtualCharMethodA,
2216 JNI::CallNonvirtualShortMethod,
2217 JNI::CallNonvirtualShortMethodV,
2218 JNI::CallNonvirtualShortMethodA,
2219 JNI::CallNonvirtualIntMethod,
2220 JNI::CallNonvirtualIntMethodV,
2221 JNI::CallNonvirtualIntMethodA,
2222 JNI::CallNonvirtualLongMethod,
2223 JNI::CallNonvirtualLongMethodV,
2224 JNI::CallNonvirtualLongMethodA,
2225 JNI::CallNonvirtualFloatMethod,
2226 JNI::CallNonvirtualFloatMethodV,
2227 JNI::CallNonvirtualFloatMethodA,
2228 JNI::CallNonvirtualDoubleMethod,
2229 JNI::CallNonvirtualDoubleMethodV,
2230 JNI::CallNonvirtualDoubleMethodA,
2231 JNI::CallNonvirtualVoidMethod,
2232 JNI::CallNonvirtualVoidMethodV,
2233 JNI::CallNonvirtualVoidMethodA,
2234 JNI::GetFieldID,
2235 JNI::GetObjectField,
2236 JNI::GetBooleanField,
2237 JNI::GetByteField,
2238 JNI::GetCharField,
2239 JNI::GetShortField,
2240 JNI::GetIntField,
2241 JNI::GetLongField,
2242 JNI::GetFloatField,
2243 JNI::GetDoubleField,
2244 JNI::SetObjectField,
2245 JNI::SetBooleanField,
2246 JNI::SetByteField,
2247 JNI::SetCharField,
2248 JNI::SetShortField,
2249 JNI::SetIntField,
2250 JNI::SetLongField,
2251 JNI::SetFloatField,
2252 JNI::SetDoubleField,
2253 JNI::GetStaticMethodID,
2254 JNI::CallStaticObjectMethod,
2255 JNI::CallStaticObjectMethodV,
2256 JNI::CallStaticObjectMethodA,
2257 JNI::CallStaticBooleanMethod,
2258 JNI::CallStaticBooleanMethodV,
2259 JNI::CallStaticBooleanMethodA,
2260 JNI::CallStaticByteMethod,
2261 JNI::CallStaticByteMethodV,
2262 JNI::CallStaticByteMethodA,
2263 JNI::CallStaticCharMethod,
2264 JNI::CallStaticCharMethodV,
2265 JNI::CallStaticCharMethodA,
2266 JNI::CallStaticShortMethod,
2267 JNI::CallStaticShortMethodV,
2268 JNI::CallStaticShortMethodA,
2269 JNI::CallStaticIntMethod,
2270 JNI::CallStaticIntMethodV,
2271 JNI::CallStaticIntMethodA,
2272 JNI::CallStaticLongMethod,
2273 JNI::CallStaticLongMethodV,
2274 JNI::CallStaticLongMethodA,
2275 JNI::CallStaticFloatMethod,
2276 JNI::CallStaticFloatMethodV,
2277 JNI::CallStaticFloatMethodA,
2278 JNI::CallStaticDoubleMethod,
2279 JNI::CallStaticDoubleMethodV,
2280 JNI::CallStaticDoubleMethodA,
2281 JNI::CallStaticVoidMethod,
2282 JNI::CallStaticVoidMethodV,
2283 JNI::CallStaticVoidMethodA,
2284 JNI::GetStaticFieldID,
2285 JNI::GetStaticObjectField,
2286 JNI::GetStaticBooleanField,
2287 JNI::GetStaticByteField,
2288 JNI::GetStaticCharField,
2289 JNI::GetStaticShortField,
2290 JNI::GetStaticIntField,
2291 JNI::GetStaticLongField,
2292 JNI::GetStaticFloatField,
2293 JNI::GetStaticDoubleField,
2294 JNI::SetStaticObjectField,
2295 JNI::SetStaticBooleanField,
2296 JNI::SetStaticByteField,
2297 JNI::SetStaticCharField,
2298 JNI::SetStaticShortField,
2299 JNI::SetStaticIntField,
2300 JNI::SetStaticLongField,
2301 JNI::SetStaticFloatField,
2302 JNI::SetStaticDoubleField,
2303 JNI::NewString,
2304 JNI::GetStringLength,
2305 JNI::GetStringChars,
2306 JNI::ReleaseStringChars,
2307 JNI::NewStringUTF,
2308 JNI::GetStringUTFLength,
2309 JNI::GetStringUTFChars,
2310 JNI::ReleaseStringUTFChars,
2311 JNI::GetArrayLength,
2312 JNI::NewObjectArray,
2313 JNI::GetObjectArrayElement,
2314 JNI::SetObjectArrayElement,
2315 JNI::NewBooleanArray,
2316 JNI::NewByteArray,
2317 JNI::NewCharArray,
2318 JNI::NewShortArray,
2319 JNI::NewIntArray,
2320 JNI::NewLongArray,
2321 JNI::NewFloatArray,
2322 JNI::NewDoubleArray,
2323 JNI::GetBooleanArrayElements,
2324 JNI::GetByteArrayElements,
2325 JNI::GetCharArrayElements,
2326 JNI::GetShortArrayElements,
2327 JNI::GetIntArrayElements,
2328 JNI::GetLongArrayElements,
2329 JNI::GetFloatArrayElements,
2330 JNI::GetDoubleArrayElements,
2331 JNI::ReleaseBooleanArrayElements,
2332 JNI::ReleaseByteArrayElements,
2333 JNI::ReleaseCharArrayElements,
2334 JNI::ReleaseShortArrayElements,
2335 JNI::ReleaseIntArrayElements,
2336 JNI::ReleaseLongArrayElements,
2337 JNI::ReleaseFloatArrayElements,
2338 JNI::ReleaseDoubleArrayElements,
2339 JNI::GetBooleanArrayRegion,
2340 JNI::GetByteArrayRegion,
2341 JNI::GetCharArrayRegion,
2342 JNI::GetShortArrayRegion,
2343 JNI::GetIntArrayRegion,
2344 JNI::GetLongArrayRegion,
2345 JNI::GetFloatArrayRegion,
2346 JNI::GetDoubleArrayRegion,
2347 JNI::SetBooleanArrayRegion,
2348 JNI::SetByteArrayRegion,
2349 JNI::SetCharArrayRegion,
2350 JNI::SetShortArrayRegion,
2351 JNI::SetIntArrayRegion,
2352 JNI::SetLongArrayRegion,
2353 JNI::SetFloatArrayRegion,
2354 JNI::SetDoubleArrayRegion,
2355 JNI::RegisterNatives,
2356 JNI::UnregisterNatives,
2357 JNI::MonitorEnter,
2358 JNI::MonitorExit,
2359 JNI::GetJavaVM,
2360 JNI::GetStringRegion,
2361 JNI::GetStringUTFRegion,
2362 JNI::GetPrimitiveArrayCritical,
2363 JNI::ReleasePrimitiveArrayCritical,
2364 JNI::GetStringCritical,
2365 JNI::ReleaseStringCritical,
2366 JNI::NewWeakGlobalRef,
2367 JNI::DeleteWeakGlobalRef,
2368 JNI::ExceptionCheck,
2369 JNI::NewDirectByteBuffer,
2370 JNI::GetDirectBufferAddress,
2371 JNI::GetDirectBufferCapacity,
2372 JNI::GetObjectRefType,
Carl Shapiroea4dca82011-08-01 13:45:38 -07002373};
2374
Elliott Hughes6c1a3942011-08-17 15:00:06 -07002375static const size_t kMonitorsInitial = 32; // Arbitrary.
2376static const size_t kMonitorsMax = 4096; // Arbitrary sanity check.
2377
2378static const size_t kLocalsInitial = 64; // Arbitrary.
2379static const size_t kLocalsMax = 512; // Arbitrary sanity check.
Elliott Hughesbbd76712011-08-17 10:25:24 -07002380
Elliott Hughes515a5bc2011-08-17 11:08:34 -07002381JNIEnvExt::JNIEnvExt(Thread* self, bool check_jni)
Elliott Hughesbbd76712011-08-17 10:25:24 -07002382 : fns(&gNativeInterface),
2383 self(self),
Elliott Hughes515a5bc2011-08-17 11:08:34 -07002384 check_jni(check_jni),
Elliott Hughesbbd76712011-08-17 10:25:24 -07002385 critical(false),
Elliott Hughes6c1a3942011-08-17 15:00:06 -07002386 monitors("monitors", kMonitorsInitial, kMonitorsMax),
2387 locals(kLocalsInitial, kLocalsMax, kLocal) {
Elliott Hughes40ef99e2011-08-11 17:44:34 -07002388}
2389
Carl Shapiroea4dca82011-08-01 13:45:38 -07002390// JNI Invocation interface.
2391
Carl Shapiro2ed144c2011-07-26 16:52:08 -07002392extern "C" jint JNI_CreateJavaVM(JavaVM** p_vm, void** p_env, void* vm_args) {
2393 const JavaVMInitArgs* args = static_cast<JavaVMInitArgs*>(vm_args);
2394 if (args->version < JNI_VERSION_1_2) {
2395 return JNI_EVERSION;
2396 }
2397 Runtime::Options options;
2398 for (int i = 0; i < args->nOptions; ++i) {
2399 JavaVMOption* option = &args->options[i];
Carl Shapirofc322c72011-07-27 00:20:01 -07002400 options.push_back(std::make_pair(StringPiece(option->optionString),
2401 option->extraInfo));
Carl Shapiro2ed144c2011-07-26 16:52:08 -07002402 }
2403 bool ignore_unrecognized = args->ignoreUnrecognized;
Elliott Hughesf2682d52011-08-15 16:37:04 -07002404 Runtime* runtime = Runtime::Create(options, ignore_unrecognized);
Carl Shapiro2ed144c2011-07-26 16:52:08 -07002405 if (runtime == NULL) {
2406 return JNI_ERR;
2407 } else {
2408 *p_env = reinterpret_cast<JNIEnv*>(Thread::Current()->GetJniEnv());
Elliott Hughes0af55432011-08-17 18:37:28 -07002409 *p_vm = reinterpret_cast<JavaVM*>(runtime->GetJavaVM());
Carl Shapiro2ed144c2011-07-26 16:52:08 -07002410 return JNI_OK;
2411 }
2412}
2413
Elliott Hughesf2682d52011-08-15 16:37:04 -07002414extern "C" jint JNI_GetCreatedJavaVMs(JavaVM** vms, jsize, jsize* vm_count) {
Carl Shapiro2ed144c2011-07-26 16:52:08 -07002415 Runtime* runtime = Runtime::Current();
2416 if (runtime == NULL) {
Elliott Hughesf2682d52011-08-15 16:37:04 -07002417 *vm_count = 0;
Carl Shapiro2ed144c2011-07-26 16:52:08 -07002418 } else {
Elliott Hughesf2682d52011-08-15 16:37:04 -07002419 *vm_count = 1;
Elliott Hughes0af55432011-08-17 18:37:28 -07002420 vms[0] = reinterpret_cast<JavaVM*>(runtime->GetJavaVM());
Carl Shapiro2ed144c2011-07-26 16:52:08 -07002421 }
2422 return JNI_OK;
2423}
2424
2425// Historically unsupported.
2426extern "C" jint JNI_GetDefaultJavaVMInitArgs(void* vm_args) {
2427 return JNI_ERR;
2428}
2429
Elliott Hughescdf53122011-08-19 15:46:09 -07002430class JII {
2431 public:
2432 static jint DestroyJavaVM(JavaVM* vm) {
2433 if (vm == NULL) {
2434 return JNI_ERR;
2435 } else {
2436 JavaVMExt* raw_vm = reinterpret_cast<JavaVMExt*>(vm);
2437 delete raw_vm->runtime;
2438 return JNI_OK;
2439 }
Carl Shapiro2ed144c2011-07-26 16:52:08 -07002440 }
Carl Shapiro2ed144c2011-07-26 16:52:08 -07002441
Elliott Hughescdf53122011-08-19 15:46:09 -07002442 static jint AttachCurrentThread(JavaVM* vm, JNIEnv** p_env, void* thr_args) {
2443 if (vm == NULL || p_env == NULL) {
2444 return JNI_ERR;
2445 }
Elliott Hughesf2682d52011-08-15 16:37:04 -07002446 JavaVMExt* raw_vm = reinterpret_cast<JavaVMExt*>(vm);
2447 Runtime* runtime = raw_vm->runtime;
Elliott Hughescdf53122011-08-19 15:46:09 -07002448 const char* name = NULL;
2449 if (thr_args != NULL) {
2450 // TODO: check version
2451 name = static_cast<JavaVMAttachArgs*>(thr_args)->name;
2452 // TODO: thread group
2453 }
2454 bool success = runtime->AttachCurrentThread(name, p_env);
2455 if (!success) {
2456 return JNI_ERR;
2457 } else {
2458 return JNI_OK;
2459 }
2460 }
2461
2462 static jint AttachCurrentThreadAsDaemon(JavaVM* vm, JNIEnv** p_env, void* thr_args) {
2463 if (vm == NULL || p_env == NULL) {
2464 return JNI_ERR;
2465 }
2466 JavaVMExt* raw_vm = reinterpret_cast<JavaVMExt*>(vm);
2467 Runtime* runtime = raw_vm->runtime;
2468 const char* name = NULL;
2469 if (thr_args != NULL) {
2470 // TODO: check version
2471 name = static_cast<JavaVMAttachArgs*>(thr_args)->name;
2472 // TODO: thread group
2473 }
2474 bool success = runtime->AttachCurrentThreadAsDaemon(name, p_env);
2475 if (!success) {
2476 return JNI_ERR;
2477 } else {
2478 return JNI_OK;
2479 }
2480 }
2481
2482 static jint DetachCurrentThread(JavaVM* vm) {
2483 if (vm == NULL) {
2484 return JNI_ERR;
2485 } else {
2486 JavaVMExt* raw_vm = reinterpret_cast<JavaVMExt*>(vm);
2487 Runtime* runtime = raw_vm->runtime;
2488 runtime->DetachCurrentThread();
2489 return JNI_OK;
2490 }
2491 }
2492
2493 static jint GetEnv(JavaVM* vm, void** env, jint version) {
2494 if (version < JNI_VERSION_1_1 || version > JNI_VERSION_1_6) {
2495 return JNI_EVERSION;
2496 }
2497 if (vm == NULL || env == NULL) {
2498 return JNI_ERR;
2499 }
2500 Thread* thread = Thread::Current();
2501 if (thread == NULL) {
2502 *env = NULL;
2503 return JNI_EDETACHED;
2504 }
2505 *env = thread->GetJniEnv();
Carl Shapiro2ed144c2011-07-26 16:52:08 -07002506 return JNI_OK;
2507 }
Elliott Hughescdf53122011-08-19 15:46:09 -07002508};
Carl Shapiro2ed144c2011-07-26 16:52:08 -07002509
Elliott Hughesf2682d52011-08-15 16:37:04 -07002510struct JNIInvokeInterface gInvokeInterface = {
Carl Shapiroea4dca82011-08-01 13:45:38 -07002511 NULL, // reserved0
2512 NULL, // reserved1
2513 NULL, // reserved2
Elliott Hughescdf53122011-08-19 15:46:09 -07002514 JII::DestroyJavaVM,
2515 JII::AttachCurrentThread,
2516 JII::DetachCurrentThread,
2517 JII::GetEnv,
2518 JII::AttachCurrentThreadAsDaemon
Carl Shapiroea4dca82011-08-01 13:45:38 -07002519};
2520
Elliott Hughesbbd76712011-08-17 10:25:24 -07002521static const size_t kPinTableInitialSize = 16;
2522static const size_t kPinTableMaxSize = 1024;
2523
Elliott Hughes6c1a3942011-08-17 15:00:06 -07002524static const size_t kGlobalsInitial = 512; // Arbitrary.
2525static const size_t kGlobalsMax = 51200; // Arbitrary sanity check.
2526
2527static const size_t kWeakGlobalsInitial = 16; // Arbitrary.
2528static const size_t kWeakGlobalsMax = 51200; // Arbitrary sanity check.
2529
Elliott Hughes0af55432011-08-17 18:37:28 -07002530JavaVMExt::JavaVMExt(Runtime* runtime, bool check_jni, bool verbose_jni)
Elliott Hughesbbd76712011-08-17 10:25:24 -07002531 : fns(&gInvokeInterface),
2532 runtime(runtime),
Elliott Hughes515a5bc2011-08-17 11:08:34 -07002533 check_jni(check_jni),
Elliott Hughes0af55432011-08-17 18:37:28 -07002534 verbose_jni(verbose_jni),
Elliott Hughes6c1a3942011-08-17 15:00:06 -07002535 pin_table("pin table", kPinTableInitialSize, kPinTableMaxSize),
Elliott Hughes18c07532011-08-18 15:50:51 -07002536 globals_lock(Mutex::Create("JNI global reference table lock")),
Elliott Hughes6c1a3942011-08-17 15:00:06 -07002537 globals(kGlobalsInitial, kGlobalsMax, kGlobal),
Elliott Hughes18c07532011-08-18 15:50:51 -07002538 weak_globals_lock(Mutex::Create("JNI weak global reference table lock")),
Elliott Hughes6c1a3942011-08-17 15:00:06 -07002539 weak_globals(kWeakGlobalsInitial, kWeakGlobalsMax, kWeakGlobal) {
Elliott Hughesf2682d52011-08-15 16:37:04 -07002540}
2541
Elliott Hughesde69d7f2011-08-18 16:49:37 -07002542JavaVMExt::~JavaVMExt() {
2543 delete globals_lock;
2544 delete weak_globals_lock;
2545}
2546
Elliott Hughescdf53122011-08-19 15:46:09 -07002547/*
2548 * Load native code from the specified absolute pathname. Per the spec,
2549 * if we've already loaded a library with the specified pathname, we
2550 * return without doing anything.
2551 *
2552 * TODO? for better results we should absolutify the pathname. For fully
2553 * correct results we should stat to get the inode and compare that. The
2554 * existing implementation is fine so long as everybody is using
2555 * System.loadLibrary.
2556 *
2557 * The library will be associated with the specified class loader. The JNI
2558 * spec says we can't load the same library into more than one class loader.
2559 *
2560 * Returns "true" on success. On failure, sets *detail to a
2561 * human-readable description of the error or NULL if no detail is
2562 * available; ownership of the string is transferred to the caller.
2563 */
Elliott Hughes814e4032011-08-23 12:07:56 -07002564bool JavaVMExt::LoadNativeLibrary(const std::string& path, ClassLoader* class_loader, char** detail) {
Elliott Hughescdf53122011-08-19 15:46:09 -07002565 *detail = NULL;
2566
2567 // See if we've already loaded this library. If we have, and the class loader
2568 // matches, return successfully without doing anything.
2569 SharedLibrary* library = libraries[path];
2570 if (library != NULL) {
2571 if (library->GetClassLoader() != class_loader) {
2572 LOG(WARNING) << "Shared library \"" << path << "\" already opened by "
2573 << "ClassLoader " << library->GetClassLoader() << "; "
2574 << "can't open in " << class_loader;
2575 *detail = strdup("already opened by different ClassLoader");
2576 return false;
2577 }
2578 if (verbose_jni) {
2579 LOG(INFO) << "[Shared library \"" << path << "\" already loaded in "
2580 << "ClassLoader " << class_loader << "]";
2581 }
2582 if (!library->CheckOnLoadResult(this)) {
2583 *detail = strdup("JNI_OnLoad failed before");
2584 return false;
2585 }
2586 return true;
2587 }
2588
2589 // Open the shared library. Because we're using a full path, the system
2590 // doesn't have to search through LD_LIBRARY_PATH. (It may do so to
2591 // resolve this library's dependencies though.)
2592
2593 // Failures here are expected when java.library.path has several entries
2594 // and we have to hunt for the lib.
2595
2596 // The current version of the dynamic linker prints detailed information
2597 // about dlopen() failures. Some things to check if the message is
2598 // cryptic:
2599 // - make sure the library exists on the device
2600 // - verify that the right path is being opened (the debug log message
2601 // above can help with that)
2602 // - check to see if the library is valid (e.g. not zero bytes long)
2603 // - check config/prelink-linux-arm.map to ensure that the library
2604 // is listed and is not being overrun by the previous entry (if
2605 // loading suddenly stops working on a prelinked library, this is
2606 // a good one to check)
2607 // - write a trivial app that calls sleep() then dlopen(), attach
2608 // to it with "strace -p <pid>" while it sleeps, and watch for
2609 // attempts to open nonexistent dependent shared libs
2610
2611 // TODO: automate some of these checks!
2612
2613 // This can execute slowly for a large library on a busy system, so we
2614 // want to switch from RUNNING to VMWAIT while it executes. This allows
2615 // the GC to ignore us.
2616 Thread* self = Thread::Current();
2617 Thread::State old_state = self->GetState();
2618 self->SetState(Thread::kWaiting); // TODO: VMWAIT
2619 void* handle = dlopen(path.c_str(), RTLD_LAZY);
2620 self->SetState(old_state);
2621
2622 if (verbose_jni) {
2623 LOG(INFO) << "[Call to dlopen(\"" << path << "\") returned " << handle << "]";
2624 }
2625
2626 if (handle == NULL) {
2627 *detail = strdup(dlerror());
2628 return false;
2629 }
2630
2631 // Create a new entry.
2632 library = new SharedLibrary(path, handle, class_loader);
2633 UNIMPLEMENTED(ERROR) << "missing pthread_cond_init";
2634 // pthread_cond_init(&library->onLoadCond, NULL);
2635
2636 libraries[path] = library;
2637
2638 // if (pNewEntry != pActualEntry) {
2639 // LOG(INFO) << "WOW: we lost a race to add a shared library (\"" << path << "\" ClassLoader=" << class_loader <<")";
2640 // freeSharedLibEntry(pNewEntry);
2641 // return CheckOnLoadResult(this, pActualEntry);
2642 // } else
2643 {
2644 if (verbose_jni) {
2645 LOG(INFO) << "[Added shared library \"" << path << "\" for ClassLoader " << class_loader << "]";
2646 }
2647
2648 bool result = true;
2649 void* sym = dlsym(handle, "JNI_OnLoad");
2650 if (sym == NULL) {
2651 if (verbose_jni) {
2652 LOG(INFO) << "[No JNI_OnLoad found in \"" << path << "\"]";
2653 }
2654 } else {
2655 // Call JNI_OnLoad. We have to override the current class
2656 // loader, which will always be "null" since the stuff at the
2657 // top of the stack is around Runtime.loadLibrary(). (See
2658 // the comments in the JNI FindClass function.)
Elliott Hughescdf53122011-08-19 15:46:09 -07002659 typedef int (*JNI_OnLoadFn)(JavaVM*, void*);
2660 JNI_OnLoadFn jni_on_load = reinterpret_cast<JNI_OnLoadFn>(sym);
Elliott Hughes814e4032011-08-23 12:07:56 -07002661 ClassLoader* old_class_loader = self->GetClassLoaderOverride();
2662 self->SetClassLoaderOverride(class_loader);
Elliott Hughescdf53122011-08-19 15:46:09 -07002663
2664 old_state = self->GetState();
2665 self->SetState(Thread::kNative);
2666 if (verbose_jni) {
2667 LOG(INFO) << "[Calling JNI_OnLoad in \"" << path << "\"]";
2668 }
2669 int version = (*jni_on_load)(reinterpret_cast<JavaVM*>(this), NULL);
2670 self->SetState(old_state);
2671
Elliott Hughes814e4032011-08-23 12:07:56 -07002672 self->SetClassLoaderOverride(old_class_loader);;
Elliott Hughescdf53122011-08-19 15:46:09 -07002673
2674 if (version != JNI_VERSION_1_2 &&
2675 version != JNI_VERSION_1_4 &&
2676 version != JNI_VERSION_1_6) {
2677 LOG(WARNING) << "JNI_OnLoad in \"" << path << "\" returned "
2678 << "bad version: " << version;
2679 // It's unwise to call dlclose() here, but we can mark it
2680 // as bad and ensure that future load attempts will fail.
2681 // We don't know how far JNI_OnLoad got, so there could
2682 // be some partially-initialized stuff accessible through
2683 // newly-registered native method calls. We could try to
2684 // unregister them, but that doesn't seem worthwhile.
2685 result = false;
2686 } else {
2687 if (verbose_jni) {
2688 LOG(INFO) << "[Returned " << (result ? "successfully" : "failure")
2689 << " from JNI_OnLoad in \"" << path << "\"]";
2690 }
2691 }
2692 }
2693
2694 library->SetResult(result);
2695 return result;
2696 }
2697}
2698
Ian Rogersdf20fe02011-07-20 20:34:16 -07002699} // namespace art