blob: a55cdae350d79ef488f1527dff280fa9d689cb7d [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
21namespace art {
22
Elliott Hughescdf53122011-08-19 15:46:09 -070023// This is private API, but with two different implementations: ARM and x86.
24void CreateInvokeStub(Assembler* assembler, Method* method);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -070025
Elliott Hughescdf53122011-08-19 15:46:09 -070026// TODO: this should be in our anonymous namespace, but is currently needed
27// for testing in "jni_internal_test.cc".
28bool EnsureInvokeStub(Method* method) {
29 if (method->GetInvokeStub() != NULL) {
30 return true;
31 }
32 // TODO: use signature to find a matching stub
33 // TODO: failed, acquire a lock on the stub table
34 Assembler assembler;
35 CreateInvokeStub(&assembler, method);
36 // TODO: store native_entry in the stub table
37 int prot = PROT_READ | PROT_WRITE | PROT_EXEC;
38 size_t length = assembler.CodeSize();
39 void* addr = mmap(NULL, length, prot, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
40 if (addr == MAP_FAILED) {
41 PLOG(FATAL) << "mmap failed";
42 }
43 MemoryRegion region(addr, length);
44 assembler.FinalizeInstructions(region);
45 method->SetInvokeStub(reinterpret_cast<Method::InvokeStub*>(region.pointer()));
46 return true;
47}
Elliott Hughes0af55432011-08-17 18:37:28 -070048
Elliott Hughescdf53122011-08-19 15:46:09 -070049// TODO: this can't be in our anonymous namespace because of the map in JavaVM.
50class SharedLibrary {
51public:
52 SharedLibrary(const std::string& path, void* handle, Object* class_loader)
53 : path_(path),
54 handle_(handle),
55 jni_on_load_lock_(Mutex::Create("JNI_OnLoad lock")),
56 jni_on_load_tid_(Thread::Current()->GetId()),
57 jni_on_load_result_(kPending) {
Elliott Hughes18c07532011-08-18 15:50:51 -070058 }
59
60 ~SharedLibrary() {
Elliott Hughescdf53122011-08-19 15:46:09 -070061 delete jni_on_load_lock_;
Elliott Hughes0af55432011-08-17 18:37:28 -070062 }
63
Elliott Hughescdf53122011-08-19 15:46:09 -070064 Object* GetClassLoader() {
65 return class_loader_;
Elliott Hughes0af55432011-08-17 18:37:28 -070066 }
67
Elliott Hughescdf53122011-08-19 15:46:09 -070068 /*
69 * Check the result of an earlier call to JNI_OnLoad on this library. If
70 * the call has not yet finished in another thread, wait for it.
71 */
72 bool CheckOnLoadResult(JavaVMExt* vm) {
73 Thread* self = Thread::Current();
74 if (jni_on_load_tid_ == self->GetId()) {
75 // Check this so we don't end up waiting for ourselves. We need
76 // to return "true" so the caller can continue.
77 LOG(INFO) << *self << " recursive attempt to load library "
78 << "\"" << path_ << "\"";
79 return true;
Elliott Hughes0af55432011-08-17 18:37:28 -070080 }
81
Elliott Hughescdf53122011-08-19 15:46:09 -070082 UNIMPLEMENTED(ERROR) << "need to pthread_cond_wait!";
83 // MutexLock mu(jni_on_load_lock_);
84 while (jni_on_load_result_ == kPending) {
85 if (vm->verbose_jni) {
86 LOG(INFO) << "[" << *self << " waiting for \"" << path_ << "\" "
87 << "JNI_OnLoad...]";
Elliott Hughes0af55432011-08-17 18:37:28 -070088 }
Elliott Hughescdf53122011-08-19 15:46:09 -070089 Thread::State old_state = self->GetState();
90 self->SetState(Thread::kWaiting); // TODO: VMWAIT
91 // pthread_cond_wait(&jni_on_load_cond_, &jni_on_load_lock_);
Elliott Hughes0af55432011-08-17 18:37:28 -070092 self->SetState(old_state);
Elliott Hughes0af55432011-08-17 18:37:28 -070093 }
94
Elliott Hughescdf53122011-08-19 15:46:09 -070095 bool okay = (jni_on_load_result_ == kOkay);
96 if (vm->verbose_jni) {
97 LOG(INFO) << "[Earlier JNI_OnLoad for \"" << path_ << "\" "
98 << (okay ? "succeeded" : "failed") << "]";
99 }
100 return okay;
101 }
102
103 void SetResult(bool result) {
104 jni_on_load_result_ = result ? kOkay : kFailed;
105 jni_on_load_tid_ = 0;
Elliott Hughes0af55432011-08-17 18:37:28 -0700106
107 // Broadcast a wakeup to anybody sleeping on the condition variable.
108 UNIMPLEMENTED(ERROR) << "missing pthread_cond_broadcast";
Elliott Hughescdf53122011-08-19 15:46:09 -0700109 // MutexLock mu(library->jni_on_load_lock_);
110 // pthread_cond_broadcast(&library->jni_on_load_cond_);
Elliott Hughes0af55432011-08-17 18:37:28 -0700111 }
Elliott Hughescdf53122011-08-19 15:46:09 -0700112
113 private:
114 enum JNI_OnLoadState {
115 kPending,
116 kFailed,
117 kOkay,
118 };
119
120 // Path to library "/system/lib/libjni.so".
121 std::string path_;
122
123 // The void* returned by dlopen(3).
124 void* handle_;
125
126 // The ClassLoader this library is associated with.
127 Object* class_loader_;
128
129 // Guards remaining items.
130 Mutex* jni_on_load_lock_;
131 // Wait for JNI_OnLoad in other thread.
132 pthread_cond_t jni_on_load_cond_;
133 // Recursive invocation guard.
134 uint32_t jni_on_load_tid_;
135 // Result of earlier JNI_OnLoad call.
136 JNI_OnLoadState jni_on_load_result_;
137};
138
139namespace {
Elliott Hughes0af55432011-08-17 18:37:28 -0700140
Elliott Hughes22f40932011-08-12 13:06:37 -0700141// Entry/exit processing for all JNI calls.
142//
143// This performs the necessary thread state switching, lets us amortize the
144// cost of working out the current thread, and lets us check (and repair) apps
145// that are using a JNIEnv on the wrong thread.
146class ScopedJniThreadState {
147 public:
Elliott Hughesc5f7c912011-08-18 14:00:42 -0700148 explicit ScopedJniThreadState(JNIEnv* env)
149 : env_(reinterpret_cast<JNIEnvExt*>(env)) {
Elliott Hughesb20a5542011-08-12 18:03:12 -0700150 self_ = ThreadForEnv(env);
Elliott Hughes22f40932011-08-12 13:06:37 -0700151 self_->SetState(Thread::kRunnable);
152 }
153
154 ~ScopedJniThreadState() {
155 self_->SetState(Thread::kNative);
156 }
157
Elliott Hughesc5f7c912011-08-18 14:00:42 -0700158 JNIEnvExt* Env() {
159 return env_;
160 }
161
Elliott Hughesb20a5542011-08-12 18:03:12 -0700162 Thread* Self() {
Elliott Hughes22f40932011-08-12 13:06:37 -0700163 return self_;
164 }
165
Elliott Hughesb20a5542011-08-12 18:03:12 -0700166 private:
167 static Thread* ThreadForEnv(JNIEnv* env) {
Elliott Hughes22f40932011-08-12 13:06:37 -0700168 // TODO: need replacement for gDvmJni.
169 bool workAroundAppJniBugs = true;
170 Thread* env_self = reinterpret_cast<JNIEnvExt*>(env)->self;
171 Thread* self = workAroundAppJniBugs ? Thread::Current() : env_self;
172 if (self != env_self) {
Elliott Hughes330304d2011-08-12 14:28:05 -0700173 LOG(ERROR) << "JNI ERROR: JNIEnv for " << *env_self
174 << " used on " << *self;
175 // TODO: dump stack
Elliott Hughes22f40932011-08-12 13:06:37 -0700176 }
177 return self;
178 }
179
Elliott Hughesc5f7c912011-08-18 14:00:42 -0700180 JNIEnvExt* env_;
Elliott Hughes22f40932011-08-12 13:06:37 -0700181 Thread* self_;
182 DISALLOW_COPY_AND_ASSIGN(ScopedJniThreadState);
183};
184
Elliott Hughesc5f7c912011-08-18 14:00:42 -0700185/*
186 * Add a local reference for an object to the current stack frame. When
187 * the native function returns, the reference will be discarded.
188 *
189 * We need to allow the same reference to be added multiple times.
190 *
191 * This will be called on otherwise unreferenced objects. We cannot do
192 * GC allocations here, and it's best if we don't grab a mutex.
193 *
194 * Returns the local reference (currently just the same pointer that was
195 * passed in), or NULL on failure.
196 */
Elliott Hughes8a26c5c2011-08-15 18:35:43 -0700197template<typename T>
198T AddLocalReference(ScopedJniThreadState& ts, Object* obj) {
Elliott Hughesc5f7c912011-08-18 14:00:42 -0700199 if (obj == NULL) {
200 return NULL;
201 }
202
203 IndirectReferenceTable& locals = ts.Env()->locals;
204
205 uint32_t cookie = IRT_FIRST_SEGMENT; // TODO
206 IndirectRef ref = locals.Add(cookie, obj);
207 if (ref == NULL) {
208 // TODO: just change Add's DCHECK to CHECK and lose this?
209 locals.Dump();
210 LOG(FATAL) << "Failed adding to JNI local reference table "
211 << "(has " << locals.Capacity() << " entries)";
212 // TODO: dvmDumpThread(dvmThreadSelf(), false);
213 }
214
215#if 0 // TODO: fix this to understand PushLocalFrame, so we can turn it on.
216 if (ts.Env()->check_jni) {
217 size_t entry_count = locals.Capacity();
218 if (entry_count > 16) {
219 std::string class_name(PrettyDescriptor(obj->GetClass()->GetDescriptor()));
220 LOG(WARNING) << "Warning: more than 16 JNI local references: "
221 << entry_count << " (most recent was a " << class_name << ")";
222 locals.Dump();
223 // TODO: dvmDumpThread(dvmThreadSelf(), false);
224 // dvmAbort();
225 }
226 }
227#endif
228
229 if (false /*gDvmJni.workAroundAppJniBugs*/) { // TODO
230 // Hand out direct pointers to support broken old apps.
231 return reinterpret_cast<T>(obj);
232 }
233
234 return reinterpret_cast<T>(ref);
235}
236
Elliott Hughescdf53122011-08-19 15:46:09 -0700237jweak AddWeakGlobalReference(ScopedJniThreadState& ts, Object* obj) {
238 if (obj == NULL) {
239 return NULL;
240 }
241 JavaVMExt* vm = Runtime::Current()->GetJavaVM();
242 IndirectReferenceTable& weak_globals = vm->weak_globals;
243 MutexLock mu(vm->weak_globals_lock);
244 IndirectRef ref = weak_globals.Add(IRT_FIRST_SEGMENT, obj);
245 return reinterpret_cast<jweak>(ref);
246}
247
Elliott Hughesc5f7c912011-08-18 14:00:42 -0700248template<typename T>
249T Decode(ScopedJniThreadState& ts, jobject obj) {
250 if (obj == NULL) {
251 return NULL;
252 }
253
254 IndirectRef ref = reinterpret_cast<IndirectRef>(obj);
255 IndirectRefKind kind = GetIndirectRefKind(ref);
256 Object* result;
257 switch (kind) {
258 case kLocal:
259 {
260 IndirectReferenceTable& locals = ts.Env()->locals;
261 result = locals.Get(ref);
262 break;
263 }
264 case kGlobal:
265 {
266 JavaVMExt* vm = Runtime::Current()->GetJavaVM();
267 IndirectReferenceTable& globals = vm->globals;
Elliott Hughes18c07532011-08-18 15:50:51 -0700268 MutexLock mu(vm->globals_lock);
Elliott Hughesc5f7c912011-08-18 14:00:42 -0700269 result = globals.Get(ref);
270 break;
271 }
272 case kWeakGlobal:
273 {
274 JavaVMExt* vm = Runtime::Current()->GetJavaVM();
275 IndirectReferenceTable& weak_globals = vm->weak_globals;
Elliott Hughes18c07532011-08-18 15:50:51 -0700276 MutexLock mu(vm->weak_globals_lock);
Elliott Hughesc5f7c912011-08-18 14:00:42 -0700277 result = weak_globals.Get(ref);
278 if (result == kClearedJniWeakGlobal) {
279 // This is a special case where it's okay to return NULL.
280 return NULL;
281 }
282 break;
283 }
284 case kInvalid:
285 default:
Ian Rogersa8cd9f42011-08-19 16:43:41 -0700286 // TODO: make stack handle blocks more efficient
287 // Check if this is a local reference in a stack handle block
288 if (ts.Self()->ShbContains(obj)) {
289 return *reinterpret_cast<T*>(obj); // Read from stack handle block
290 }
Elliott Hughesc5f7c912011-08-18 14:00:42 -0700291 if (false /*gDvmJni.workAroundAppJniBugs*/) { // TODO
292 // Assume an invalid local reference is actually a direct pointer.
293 return reinterpret_cast<T>(obj);
294 }
295 LOG(FATAL) << "Invalid indirect reference " << obj;
296 return reinterpret_cast<T>(kInvalidIndirectRefObject);
297 }
298
299 if (result == NULL) {
300 LOG(FATAL) << "JNI ERROR (app bug): use of deleted " << kind << ": "
301 << obj;
302 }
303 return reinterpret_cast<T>(result);
Elliott Hughes8a26c5c2011-08-15 18:35:43 -0700304}
305
Elliott Hughescdf53122011-08-19 15:46:09 -0700306Field* DecodeField(ScopedJniThreadState& ts, jfieldID fid) {
307 return Decode<Field*>(ts, reinterpret_cast<jweak>(fid));
308}
Carl Shapiro9b9ba282011-08-14 15:30:39 -0700309
Elliott Hughescdf53122011-08-19 15:46:09 -0700310Method* DecodeMethod(ScopedJniThreadState& ts, jmethodID mid) {
311 return Decode<Method*>(ts, reinterpret_cast<jweak>(mid));
Carl Shapiro9b9ba282011-08-14 15:30:39 -0700312}
313
Elliott Hughesc5f7c912011-08-18 14:00:42 -0700314byte* CreateArgArray(ScopedJniThreadState& ts, Method* method, va_list ap) {
Carl Shapiro9b9ba282011-08-14 15:30:39 -0700315 size_t num_bytes = method->NumArgArrayBytes();
316 scoped_array<byte> arg_array(new byte[num_bytes]);
317 const StringPiece& shorty = method->GetShorty();
Ian Rogers4dd71f12011-08-16 14:16:02 -0700318 for (int i = 1, offset = 0; i < shorty.size(); ++i) {
Carl Shapiro9b9ba282011-08-14 15:30:39 -0700319 switch (shorty[i]) {
320 case 'Z':
321 case 'B':
322 case 'C':
323 case 'S':
324 case 'I':
325 *reinterpret_cast<int32_t*>(&arg_array[offset]) = va_arg(ap, jint);
326 offset += 4;
327 break;
328 case 'F':
329 *reinterpret_cast<float*>(&arg_array[offset]) = va_arg(ap, jdouble);
330 offset += 4;
331 break;
332 case 'L': {
Elliott Hughesc5f7c912011-08-18 14:00:42 -0700333 Object* obj = Decode<Object*>(ts, va_arg(ap, jobject));
Carl Shapiro9b9ba282011-08-14 15:30:39 -0700334 *reinterpret_cast<Object**>(&arg_array[offset]) = obj;
335 offset += sizeof(Object*);
336 break;
337 }
338 case 'D':
339 *reinterpret_cast<double*>(&arg_array[offset]) = va_arg(ap, jdouble);
340 offset += 8;
341 break;
342 case 'J':
343 *reinterpret_cast<int64_t*>(&arg_array[offset]) = va_arg(ap, jlong);
344 offset += 8;
345 break;
346 }
347 }
348 return arg_array.release();
349}
350
Elliott Hughesc5f7c912011-08-18 14:00:42 -0700351byte* CreateArgArray(ScopedJniThreadState& ts, Method* method, jvalue* args) {
Carl Shapiro9b9ba282011-08-14 15:30:39 -0700352 size_t num_bytes = method->NumArgArrayBytes();
353 scoped_array<byte> arg_array(new byte[num_bytes]);
354 const StringPiece& shorty = method->GetShorty();
Ian Rogers4dd71f12011-08-16 14:16:02 -0700355 for (int i = 1, offset = 0; i < shorty.size(); ++i) {
Carl Shapiro9b9ba282011-08-14 15:30:39 -0700356 switch (shorty[i]) {
357 case 'Z':
358 case 'B':
359 case 'C':
360 case 'S':
361 case 'I':
362 *reinterpret_cast<uint32_t*>(&arg_array[offset]) = args[i - 1].i;
363 offset += 4;
364 break;
365 case 'F':
366 *reinterpret_cast<float*>(&arg_array[offset]) = args[i - 1].f;
367 offset += 4;
368 break;
369 case 'L': {
Elliott Hughesc5f7c912011-08-18 14:00:42 -0700370 Object* obj = Decode<Object*>(ts, args[i - 1].l);
Carl Shapiro9b9ba282011-08-14 15:30:39 -0700371 *reinterpret_cast<Object**>(&arg_array[offset]) = obj;
372 offset += sizeof(Object*);
373 break;
374 }
375 case 'D':
376 *reinterpret_cast<double*>(&arg_array[offset]) = args[i - 1].d;
377 offset += 8;
378 break;
379 case 'J':
380 *reinterpret_cast<uint64_t*>(&arg_array[offset]) = args[i - 1].j;
381 offset += 8;
382 break;
383 }
384 }
385 return arg_array.release();
386}
387
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700388JValue InvokeWithArgArray(ScopedJniThreadState& ts, jobject obj,
Elliott Hughescdf53122011-08-19 15:46:09 -0700389 jmethodID mid, byte* args) {
390 Method* method = DecodeMethod(ts, mid);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700391 Object* rcvr = Decode<Object*>(ts, obj);
Ian Rogers6de08602011-08-19 14:52:39 -0700392 Thread* self = ts.Self();
393
394 // Push a transition back into managed code onto the linked list in thread
395 CHECK_EQ(Thread::kRunnable, self->GetState());
396 NativeToManagedRecord record;
397 self->PushNativeToManagedRecord(&record);
398
Carl Shapiro9b9ba282011-08-14 15:30:39 -0700399 // Call the invoke stub associated with the method
400 // Pass everything as arguments
401 const Method::InvokeStub* stub = method->GetInvokeStub();
402 CHECK(stub != NULL);
Carl Shapiro9b9ba282011-08-14 15:30:39 -0700403 JValue result;
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700404 // TODO: we should always have code associated with a method
405 if (method->GetCode()) {
Ian Rogers6de08602011-08-19 14:52:39 -0700406 (*stub)(method, rcvr, self, args, &result);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700407 } else {
408 // TODO: pretty print method here
409 LOG(WARNING) << "Not invoking method with no associated code";
410 result.j = 0;
411 }
Ian Rogers6de08602011-08-19 14:52:39 -0700412 // Pop transition
413 self->PopNativeToManagedRecord(record);
Carl Shapiro9b9ba282011-08-14 15:30:39 -0700414 return result;
415}
416
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700417JValue InvokeWithJValues(ScopedJniThreadState& ts, jobject obj,
Elliott Hughescdf53122011-08-19 15:46:09 -0700418 jmethodID mid, jvalue* args) {
419 Method* method = DecodeMethod(ts, mid);
Elliott Hughesc5f7c912011-08-18 14:00:42 -0700420 scoped_array<byte> arg_array(CreateArgArray(ts, method, args));
Elliott Hughescdf53122011-08-19 15:46:09 -0700421 return InvokeWithArgArray(ts, obj, mid, arg_array.get());
Carl Shapiro9b9ba282011-08-14 15:30:39 -0700422}
423
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700424JValue InvokeWithVarArgs(ScopedJniThreadState& ts, jobject obj,
Elliott Hughescdf53122011-08-19 15:46:09 -0700425 jmethodID mid, va_list args) {
426 Method* method = DecodeMethod(ts, mid);
Elliott Hughesc5f7c912011-08-18 14:00:42 -0700427 scoped_array<byte> arg_array(CreateArgArray(ts, method, args));
Elliott Hughescdf53122011-08-19 15:46:09 -0700428 return InvokeWithArgArray(ts, obj, mid, arg_array.get());
Carl Shapiroea4dca82011-08-01 13:45:38 -0700429}
430
Elliott Hughes6b436852011-08-12 10:16:44 -0700431// Section 12.3.2 of the JNI spec describes JNI class descriptors. They're
432// separated with slashes but aren't wrapped with "L;" like regular descriptors
433// (i.e. "a/b/C" rather than "La/b/C;"). Arrays of reference types are an
434// exception; there the "L;" must be present ("[La/b/C;"). Historically we've
435// supported names with dots too (such as "a.b.C").
436std::string NormalizeJniClassDescriptor(const char* name) {
437 std::string result;
438 // Add the missing "L;" if necessary.
439 if (name[0] == '[') {
440 result = name;
441 } else {
442 result += 'L';
443 result += name;
444 result += ';';
445 }
446 // Rewrite '.' as '/' for backwards compatibility.
Elliott Hughesa5b897e2011-08-16 11:33:06 -0700447 if (result.find('.') != std::string::npos) {
448 LOG(WARNING) << "Call to JNI FindClass with dots in name: "
449 << "\"" << name << "\"";
450 std::replace(result.begin(), result.end(), '.', '/');
Elliott Hughes6b436852011-08-12 10:16:44 -0700451 }
452 return result;
453}
454
Elliott Hughescdf53122011-08-19 15:46:09 -0700455jmethodID FindMethodID(ScopedJniThreadState& ts, jclass jni_class, const char* name, const char* sig, bool is_static) {
456 Class* c = Decode<Class*>(ts, jni_class);
Elliott Hughesf4c21c92011-08-19 17:31:31 -0700457 if (!Runtime::Current()->GetClassLinker()->EnsureInitialized(c)) {
458 return NULL;
Carl Shapiro83ab4f32011-08-15 20:21:39 -0700459 }
Elliott Hughescdf53122011-08-19 15:46:09 -0700460
461 Method* method = NULL;
462 if (is_static) {
463 method = c->FindDirectMethod(name, sig);
Ian Rogers4dd71f12011-08-16 14:16:02 -0700464 } else {
Elliott Hughescdf53122011-08-19 15:46:09 -0700465 method = c->FindVirtualMethod(name, sig);
466 if (method == NULL) {
467 // No virtual method matching the signature. Search declared
468 // private methods and constructors.
469 method = c->FindDeclaredDirectMethod(name, sig);
Ian Rogers4dd71f12011-08-16 14:16:02 -0700470 }
Carl Shapiro83ab4f32011-08-15 20:21:39 -0700471 }
Carl Shapiroea4dca82011-08-01 13:45:38 -0700472
Elliott Hughescdf53122011-08-19 15:46:09 -0700473 if (method == NULL || method->IsStatic() != is_static) {
474 Thread* self = Thread::Current();
Brian Carlstrom9cff8e12011-08-18 16:47:29 -0700475 std::string class_name(c->GetDescriptor()->ToModifiedUtf8());
Elliott Hughescdf53122011-08-19 15:46:09 -0700476 // TODO: try searching for the opposite kind of method from is_static
477 // for better diagnostics?
478 self->ThrowNewException("Ljava/lang/NoSuchMethodError;",
479 "no %s method \"%s.%s%s\"", is_static ? "static" : "non-static",
480 class_name.c_str(), name, sig);
481 return NULL;
482 }
Carl Shapiroea4dca82011-08-01 13:45:38 -0700483
Elliott Hughescdf53122011-08-19 15:46:09 -0700484 bool success = EnsureInvokeStub(method);
485 if (!success) {
486 // TODO: throw OutOfMemoryException
487 return NULL;
488 }
Carl Shapiroea4dca82011-08-01 13:45:38 -0700489
Elliott Hughescdf53122011-08-19 15:46:09 -0700490 return reinterpret_cast<jmethodID>(AddWeakGlobalReference(ts, method));
Carl Shapiroea4dca82011-08-01 13:45:38 -0700491}
492
Elliott Hughescdf53122011-08-19 15:46:09 -0700493jfieldID FindFieldID(ScopedJniThreadState& ts, jclass jni_class, const char* name, const char* sig, bool is_static) {
494 Class* c = Decode<Class*>(ts, jni_class);
Elliott Hughesf4c21c92011-08-19 17:31:31 -0700495 if (!Runtime::Current()->GetClassLinker()->EnsureInitialized(c)) {
496 return NULL;
Carl Shapiro83ab4f32011-08-15 20:21:39 -0700497 }
Elliott Hughescdf53122011-08-19 15:46:09 -0700498
499 Field* field = NULL;
500 if (is_static) {
501 field = c->FindStaticField(name, sig);
Ian Rogers4dd71f12011-08-16 14:16:02 -0700502 } else {
Elliott Hughescdf53122011-08-19 15:46:09 -0700503 field = c->FindInstanceField(name, sig);
Carl Shapiro9b9ba282011-08-14 15:30:39 -0700504 }
Carl Shapiroea4dca82011-08-01 13:45:38 -0700505
Elliott Hughescdf53122011-08-19 15:46:09 -0700506 if (field == NULL) {
507 Thread* self = Thread::Current();
Brian Carlstrom9cff8e12011-08-18 16:47:29 -0700508 std::string class_name(c->GetDescriptor()->ToModifiedUtf8());
Elliott Hughescdf53122011-08-19 15:46:09 -0700509 self->ThrowNewException("Ljava/lang/NoSuchFieldError;",
510 "no \"%s\" field \"%s\" in class \"%s\" or its superclasses", sig,
511 name, class_name.c_str());
Elliott Hughes8a26c5c2011-08-15 18:35:43 -0700512 return NULL;
513 }
Carl Shapiroea4dca82011-08-01 13:45:38 -0700514
Elliott Hughescdf53122011-08-19 15:46:09 -0700515 jweak fid = AddWeakGlobalReference(ts, field);
516 return reinterpret_cast<jfieldID>(fid);
Carl Shapiroea4dca82011-08-01 13:45:38 -0700517}
518
Elliott Hughesd8ddfd52011-08-15 14:32:53 -0700519template<typename JniT, typename ArtT>
520JniT NewPrimitiveArray(ScopedJniThreadState& ts, jsize length) {
521 CHECK_GE(length, 0); // TODO: ReportJniError
522 ArtT* result = ArtT::Alloc(length);
Elliott Hughes8a26c5c2011-08-15 18:35:43 -0700523 return AddLocalReference<JniT>(ts, result);
Elliott Hughesd8ddfd52011-08-15 14:32:53 -0700524}
525
Elliott Hughescdf53122011-08-19 15:46:09 -0700526} // namespace
Carl Shapiroea4dca82011-08-01 13:45:38 -0700527
Elliott Hughescdf53122011-08-19 15:46:09 -0700528class JNI {
529 public:
Carl Shapiroea4dca82011-08-01 13:45:38 -0700530
Elliott Hughescdf53122011-08-19 15:46:09 -0700531 static jint GetVersion(JNIEnv* env) {
532 ScopedJniThreadState ts(env);
533 return JNI_VERSION_1_6;
534 }
Carl Shapiroea4dca82011-08-01 13:45:38 -0700535
Elliott Hughescdf53122011-08-19 15:46:09 -0700536 static jclass DefineClass(JNIEnv* env, const char*, jobject, const jbyte*, jsize) {
537 ScopedJniThreadState ts(env);
538 LOG(WARNING) << "JNI DefineClass is not supported";
Elliott Hughesf2682d52011-08-15 16:37:04 -0700539 return NULL;
540 }
541
Elliott Hughescdf53122011-08-19 15:46:09 -0700542 static jclass FindClass(JNIEnv* env, const char* name) {
543 ScopedJniThreadState ts(env);
544 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
545 std::string descriptor(NormalizeJniClassDescriptor(name));
546 // TODO: need to get the appropriate ClassLoader.
547 Class* c = class_linker->FindClass(descriptor, NULL);
548 return AddLocalReference<jclass>(ts, c);
Ian Rogers4dd71f12011-08-16 14:16:02 -0700549 }
Carl Shapiroea4dca82011-08-01 13:45:38 -0700550
Elliott Hughescdf53122011-08-19 15:46:09 -0700551 static jmethodID FromReflectedMethod(JNIEnv* env, jobject java_method) {
552 ScopedJniThreadState ts(env);
553 Method* method = Decode<Method*>(ts, java_method);
554 return reinterpret_cast<jmethodID>(AddWeakGlobalReference(ts, method));
Elliott Hughesf2682d52011-08-15 16:37:04 -0700555 }
Carl Shapiroea4dca82011-08-01 13:45:38 -0700556
Elliott Hughescdf53122011-08-19 15:46:09 -0700557 static jfieldID FromReflectedField(JNIEnv* env, jobject java_field) {
558 ScopedJniThreadState ts(env);
559 Field* field = Decode<Field*>(ts, java_field);
560 return reinterpret_cast<jfieldID>(AddWeakGlobalReference(ts, field));
561 }
Carl Shapiroea4dca82011-08-01 13:45:38 -0700562
Elliott Hughescdf53122011-08-19 15:46:09 -0700563 static jobject ToReflectedMethod(JNIEnv* env, jclass, jmethodID mid, jboolean) {
564 ScopedJniThreadState ts(env);
565 Method* method = DecodeMethod(ts, mid);
566 return AddLocalReference<jobject>(ts, method);
567 }
Carl Shapiroea4dca82011-08-01 13:45:38 -0700568
Elliott Hughescdf53122011-08-19 15:46:09 -0700569 static jobject ToReflectedField(JNIEnv* env, jclass, jfieldID fid, jboolean) {
570 ScopedJniThreadState ts(env);
571 Field* field = DecodeField(ts, fid);
572 return AddLocalReference<jobject>(ts, field);
573 }
Carl Shapiroea4dca82011-08-01 13:45:38 -0700574
Elliott Hughescdf53122011-08-19 15:46:09 -0700575 static jclass GetSuperclass(JNIEnv* env, jclass sub) {
576 ScopedJniThreadState ts(env);
577 UNIMPLEMENTED(FATAL);
578 return NULL;
579 }
Carl Shapiroea4dca82011-08-01 13:45:38 -0700580
Elliott Hughescdf53122011-08-19 15:46:09 -0700581 static jboolean IsAssignableFrom(JNIEnv* env, jclass sub, jclass sup) {
582 ScopedJniThreadState ts(env);
583 UNIMPLEMENTED(FATAL);
584 return JNI_FALSE;
585 }
Carl Shapiroea4dca82011-08-01 13:45:38 -0700586
Elliott Hughescdf53122011-08-19 15:46:09 -0700587 static jint Throw(JNIEnv* env, jthrowable obj) {
588 ScopedJniThreadState ts(env);
589 UNIMPLEMENTED(FATAL);
590 return 0;
591 }
Carl Shapiroea4dca82011-08-01 13:45:38 -0700592
Elliott Hughescdf53122011-08-19 15:46:09 -0700593 static jint ThrowNew(JNIEnv* env, jclass clazz, const char* msg) {
594 ScopedJniThreadState ts(env);
595 UNIMPLEMENTED(FATAL);
596 return 0;
597 }
Carl Shapiroea4dca82011-08-01 13:45:38 -0700598
Elliott Hughescdf53122011-08-19 15:46:09 -0700599 static jthrowable ExceptionOccurred(JNIEnv* env) {
600 ScopedJniThreadState ts(env);
601 Object* exception = ts.Self()->GetException();
602 if (exception == NULL) {
603 return NULL;
604 } else {
605 // TODO: if adding a local reference failing causes the VM to abort
606 // then the following check will never occur.
607 jthrowable localException = AddLocalReference<jthrowable>(ts, exception);
608 if (localException == NULL) {
609 // We were unable to add a new local reference, and threw a new
610 // exception. We can't return "exception", because it's not a
611 // local reference. So we have to return NULL, indicating that
612 // there was no exception, even though it's pretty much raining
613 // exceptions in here.
614 LOG(WARNING) << "JNI WARNING: addLocal/exception combo";
615 }
616 return localException;
617 }
618 }
619
620 static void ExceptionDescribe(JNIEnv* env) {
621 ScopedJniThreadState ts(env);
622 UNIMPLEMENTED(FATAL);
623 }
624
625 static void ExceptionClear(JNIEnv* env) {
626 ScopedJniThreadState ts(env);
627 ts.Self()->ClearException();
628 }
629
630 static void FatalError(JNIEnv* env, const char* msg) {
631 ScopedJniThreadState ts(env);
632 LOG(FATAL) << "JNI FatalError called: " << msg;
633 }
634
635 static jint PushLocalFrame(JNIEnv* env, jint cap) {
636 ScopedJniThreadState ts(env);
637 UNIMPLEMENTED(WARNING) << "ignoring PushLocalFrame(" << cap << ")";
638 return JNI_OK;
639 }
640
641 static jobject PopLocalFrame(JNIEnv* env, jobject res) {
642 ScopedJniThreadState ts(env);
643 UNIMPLEMENTED(WARNING) << "ignoring PopLocalFrame " << res;
644 return res;
645 }
646
647 static jobject NewGlobalRef(JNIEnv* env, jobject obj) {
648 ScopedJniThreadState ts(env);
649 if (obj == NULL) {
650 return NULL;
651 }
652
653 JavaVMExt* vm = Runtime::Current()->GetJavaVM();
654 IndirectReferenceTable& globals = vm->globals;
655 MutexLock mu(vm->globals_lock);
656 IndirectRef ref = globals.Add(IRT_FIRST_SEGMENT, Decode<Object*>(ts, obj));
657 return reinterpret_cast<jobject>(ref);
658 }
659
660 static void DeleteGlobalRef(JNIEnv* env, jobject obj) {
661 ScopedJniThreadState ts(env);
662 if (obj == NULL) {
663 return;
664 }
665
666 JavaVMExt* vm = Runtime::Current()->GetJavaVM();
667 IndirectReferenceTable& globals = vm->globals;
668 MutexLock mu(vm->globals_lock);
669
670 if (!globals.Remove(IRT_FIRST_SEGMENT, obj)) {
671 LOG(WARNING) << "JNI WARNING: DeleteGlobalRef(" << obj << ") "
672 << "failed to find entry";
673 }
674 }
675
676 static jweak NewWeakGlobalRef(JNIEnv* env, jobject obj) {
677 ScopedJniThreadState ts(env);
678 return AddWeakGlobalReference(ts, Decode<Object*>(ts, obj));
679 }
680
681 static void DeleteWeakGlobalRef(JNIEnv* env, jweak obj) {
682 ScopedJniThreadState ts(env);
683 if (obj == NULL) {
684 return;
685 }
686
687 JavaVMExt* vm = Runtime::Current()->GetJavaVM();
688 IndirectReferenceTable& weak_globals = vm->weak_globals;
689 MutexLock mu(vm->weak_globals_lock);
690
691 if (!weak_globals.Remove(IRT_FIRST_SEGMENT, obj)) {
692 LOG(WARNING) << "JNI WARNING: DeleteWeakGlobalRef(" << obj << ") "
693 << "failed to find entry";
694 }
695 }
696
697 static jobject NewLocalRef(JNIEnv* env, jobject obj) {
698 ScopedJniThreadState ts(env);
699 if (obj == NULL) {
700 return NULL;
701 }
702
703 IndirectReferenceTable& locals = ts.Env()->locals;
704
705 uint32_t cookie = IRT_FIRST_SEGMENT; // TODO
706 IndirectRef ref = locals.Add(cookie, Decode<Object*>(ts, obj));
707 return reinterpret_cast<jobject>(ref);
708 }
709
710 static void DeleteLocalRef(JNIEnv* env, jobject obj) {
711 ScopedJniThreadState ts(env);
712 if (obj == NULL) {
713 return;
714 }
715
716 IndirectReferenceTable& locals = ts.Env()->locals;
717
718 uint32_t cookie = IRT_FIRST_SEGMENT; // TODO
719 if (!locals.Remove(cookie, obj)) {
720 // Attempting to delete a local reference that is not in the
721 // topmost local reference frame is a no-op. DeleteLocalRef returns
722 // void and doesn't throw any exceptions, but we should probably
723 // complain about it so the user will notice that things aren't
724 // going quite the way they expect.
725 LOG(WARNING) << "JNI WARNING: DeleteLocalRef(" << obj << ") "
726 << "failed to find entry";
727 }
728 }
729
730 static jboolean IsSameObject(JNIEnv* env, jobject obj1, jobject obj2) {
731 ScopedJniThreadState ts(env);
732 return (Decode<Object*>(ts, obj1) == Decode<Object*>(ts, obj2))
733 ? JNI_TRUE : JNI_FALSE;
734 }
735
736 static jint EnsureLocalCapacity(JNIEnv* env, jint) {
737 ScopedJniThreadState ts(env);
738 UNIMPLEMENTED(FATAL);
739 return 0;
740 }
741
742 static jobject AllocObject(JNIEnv* env, jclass clazz) {
743 ScopedJniThreadState ts(env);
744 UNIMPLEMENTED(FATAL);
745 return NULL;
746 }
747
748 static jobject NewObject(JNIEnv* env, jclass clazz, jmethodID methodID, ...) {
749 ScopedJniThreadState ts(env);
750 va_list args;
751 va_start(args, methodID);
752 jobject result = NewObjectV(env, clazz, methodID, args);
753 va_end(args);
754 return result;
755 }
756
757 static jobject NewObjectV(JNIEnv* env,
758 jclass clazz, jmethodID methodID, va_list args) {
759 ScopedJniThreadState ts(env);
760 Class* klass = Decode<Class*>(ts, clazz);
761 Object* result = klass->NewInstance();
762 jobject local_result = AddLocalReference<jobject>(ts, result);
763 CallNonvirtualVoidMethodV(env, local_result, clazz, methodID, args);
764 return local_result;
765 }
766
767 static jobject NewObjectA(JNIEnv* env,
768 jclass clazz, jmethodID methodID, jvalue* args) {
769 ScopedJniThreadState ts(env);
770 Class* klass = Decode<Class*>(ts, clazz);
771 Object* result = klass->NewInstance();
772 jobject local_result = AddLocalReference<jobjectArray>(ts, result);
773 CallNonvirtualVoidMethodA(env, local_result, clazz, methodID, args);
774 return local_result;
775 }
776
777 static jclass GetObjectClass(JNIEnv* env, jobject obj) {
778 ScopedJniThreadState ts(env);
779 UNIMPLEMENTED(FATAL);
780 return NULL;
781 }
782
783 static jboolean IsInstanceOf(JNIEnv* env, jobject jobj, jclass clazz) {
784 ScopedJniThreadState ts(env);
785 CHECK_NE(static_cast<jclass>(NULL), clazz);
786 if (jobj == NULL) {
787 // NB. JNI is different from regular Java instanceof in this respect
788 return JNI_TRUE;
789 } else {
790 Object* obj = Decode<Object*>(ts, jobj);
791 Class* klass = Decode<Class*>(ts, clazz);
792 return Object::InstanceOf(obj, klass) ? JNI_TRUE : JNI_FALSE;
793 }
794 }
795
796 static jmethodID GetMethodID(JNIEnv* env, jclass c, const char* name, const char* sig) {
797 ScopedJniThreadState ts(env);
798 return FindMethodID(ts, c, name, sig, false);
799 }
800
801 static jmethodID GetStaticMethodID(JNIEnv* env, jclass c, const char* name, const char* sig) {
802 ScopedJniThreadState ts(env);
803 return FindMethodID(ts, c, name, sig, true);
804 }
805
806 static jobject CallObjectMethod(JNIEnv* env, jobject obj, jmethodID methodID, ...) {
807 ScopedJniThreadState ts(env);
808 UNIMPLEMENTED(FATAL);
809 return NULL;
810 }
811
812 static jobject CallObjectMethodV(JNIEnv* env,
813 jobject obj, jmethodID methodID, va_list args) {
814 ScopedJniThreadState ts(env);
815 UNIMPLEMENTED(FATAL);
816 return NULL;
817 }
818
819 static jobject CallObjectMethodA(JNIEnv* env,
820 jobject obj, jmethodID methodID, jvalue* args) {
821 ScopedJniThreadState ts(env);
822 UNIMPLEMENTED(FATAL);
823 return NULL;
824 }
825
826 static jboolean CallBooleanMethod(JNIEnv* env, jobject obj, jmethodID methodID, ...) {
827 ScopedJniThreadState ts(env);
828 UNIMPLEMENTED(FATAL);
829 return JNI_FALSE;
830 }
831
832 static jboolean CallBooleanMethodV(JNIEnv* env,
833 jobject obj, jmethodID methodID, va_list args) {
834 ScopedJniThreadState ts(env);
835 UNIMPLEMENTED(FATAL);
836 return JNI_FALSE;
837 }
838
839 static jboolean CallBooleanMethodA(JNIEnv* env,
840 jobject obj, jmethodID methodID, jvalue* args) {
841 ScopedJniThreadState ts(env);
842 UNIMPLEMENTED(FATAL);
843 return JNI_FALSE;
844 }
845
846 static jbyte CallByteMethod(JNIEnv* env, jobject obj, jmethodID methodID, ...) {
847 ScopedJniThreadState ts(env);
848 UNIMPLEMENTED(FATAL);
849 return 0;
850 }
851
852 static jbyte CallByteMethodV(JNIEnv* env,
853 jobject obj, jmethodID methodID, va_list args) {
854 ScopedJniThreadState ts(env);
855 UNIMPLEMENTED(FATAL);
856 return 0;
857 }
858
859 static jbyte CallByteMethodA(JNIEnv* env,
860 jobject obj, jmethodID methodID, jvalue* args) {
861 ScopedJniThreadState ts(env);
862 UNIMPLEMENTED(FATAL);
863 return 0;
864 }
865
866 static jchar CallCharMethod(JNIEnv* env, jobject obj, jmethodID methodID, ...) {
867 ScopedJniThreadState ts(env);
868 UNIMPLEMENTED(FATAL);
869 return 0;
870 }
871
872 static jchar CallCharMethodV(JNIEnv* env,
873 jobject obj, jmethodID methodID, va_list args) {
874 ScopedJniThreadState ts(env);
875 UNIMPLEMENTED(FATAL);
876 return 0;
877 }
878
879 static jchar CallCharMethodA(JNIEnv* env,
880 jobject obj, jmethodID methodID, jvalue* args) {
881 ScopedJniThreadState ts(env);
882 UNIMPLEMENTED(FATAL);
883 return 0;
884 }
885
886 static jshort CallShortMethod(JNIEnv* env, jobject obj, jmethodID methodID, ...) {
887 ScopedJniThreadState ts(env);
888 UNIMPLEMENTED(FATAL);
889 return 0;
890 }
891
892 static jshort CallShortMethodV(JNIEnv* env,
893 jobject obj, jmethodID methodID, va_list args) {
894 ScopedJniThreadState ts(env);
895 UNIMPLEMENTED(FATAL);
896 return 0;
897 }
898
899 static jshort CallShortMethodA(JNIEnv* env,
900 jobject obj, jmethodID methodID, jvalue* args) {
901 ScopedJniThreadState ts(env);
902 UNIMPLEMENTED(FATAL);
903 return 0;
904 }
905
906 static jint CallIntMethod(JNIEnv* env, jobject obj, jmethodID methodID, ...) {
907 ScopedJniThreadState ts(env);
908 UNIMPLEMENTED(FATAL);
909 return 0;
910 }
911
912 static jint CallIntMethodV(JNIEnv* env,
913 jobject obj, jmethodID methodID, va_list args) {
914 ScopedJniThreadState ts(env);
915 UNIMPLEMENTED(FATAL);
916 return 0;
917 }
918
919 static jint CallIntMethodA(JNIEnv* env,
920 jobject obj, jmethodID methodID, jvalue* args) {
921 ScopedJniThreadState ts(env);
922 UNIMPLEMENTED(FATAL);
923 return 0;
924 }
925
926 static jlong CallLongMethod(JNIEnv* env, jobject obj, jmethodID methodID, ...) {
927 ScopedJniThreadState ts(env);
928 UNIMPLEMENTED(FATAL);
929 return 0;
930 }
931
932 static jlong CallLongMethodV(JNIEnv* env,
933 jobject obj, jmethodID methodID, va_list args) {
934 ScopedJniThreadState ts(env);
935 UNIMPLEMENTED(FATAL);
936 return 0;
937 }
938
939 static jlong CallLongMethodA(JNIEnv* env,
940 jobject obj, jmethodID methodID, jvalue* args) {
941 ScopedJniThreadState ts(env);
942 UNIMPLEMENTED(FATAL);
943 return 0;
944 }
945
946 static jfloat CallFloatMethod(JNIEnv* env, jobject obj, jmethodID methodID, ...) {
947 ScopedJniThreadState ts(env);
948 UNIMPLEMENTED(FATAL);
949 return 0;
950 }
951
952 static jfloat CallFloatMethodV(JNIEnv* env,
953 jobject obj, jmethodID methodID, va_list args) {
954 ScopedJniThreadState ts(env);
955 UNIMPLEMENTED(FATAL);
956 return 0;
957 }
958
959 static jfloat CallFloatMethodA(JNIEnv* env,
960 jobject obj, jmethodID methodID, jvalue* args) {
961 ScopedJniThreadState ts(env);
962 UNIMPLEMENTED(FATAL);
963 return 0;
964 }
965
966 static jdouble CallDoubleMethod(JNIEnv* env, jobject obj, jmethodID methodID, ...) {
967 ScopedJniThreadState ts(env);
968 UNIMPLEMENTED(FATAL);
969 return 0;
970 }
971
972 static jdouble CallDoubleMethodV(JNIEnv* env,
973 jobject obj, jmethodID methodID, va_list args) {
974 ScopedJniThreadState ts(env);
975 UNIMPLEMENTED(FATAL);
976 return 0;
977 }
978
979 static jdouble CallDoubleMethodA(JNIEnv* env,
980 jobject obj, jmethodID methodID, jvalue* args) {
981 ScopedJniThreadState ts(env);
982 UNIMPLEMENTED(FATAL);
983 return 0;
984 }
985
986 static void CallVoidMethod(JNIEnv* env, jobject obj, jmethodID methodID, ...) {
987 ScopedJniThreadState ts(env);
988 UNIMPLEMENTED(FATAL);
989 }
990
991 static void CallVoidMethodV(JNIEnv* env, jobject obj,
992 jmethodID methodID, va_list args) {
993 ScopedJniThreadState ts(env);
994 UNIMPLEMENTED(FATAL);
995 }
996
997 static void CallVoidMethodA(JNIEnv* env, jobject obj,
998 jmethodID methodID, jvalue* args) {
999 ScopedJniThreadState ts(env);
1000 UNIMPLEMENTED(FATAL);
1001 }
1002
1003 static jobject CallNonvirtualObjectMethod(JNIEnv* env,
1004 jobject obj, jclass clazz, jmethodID methodID, ...) {
1005 ScopedJniThreadState ts(env);
1006 va_list ap;
1007 va_start(ap, methodID);
1008 JValue result = InvokeWithVarArgs(ts, obj, methodID, ap);
1009 jobject local_result = AddLocalReference<jobject>(ts, result.l);
1010 va_end(ap);
1011 return local_result;
1012 }
1013
1014 static jobject CallNonvirtualObjectMethodV(JNIEnv* env,
1015 jobject obj, jclass clazz, jmethodID methodID, va_list args) {
1016 ScopedJniThreadState ts(env);
1017 JValue result = InvokeWithVarArgs(ts, obj, methodID, args);
1018 return AddLocalReference<jobject>(ts, result.l);
1019 }
1020
1021 static jobject CallNonvirtualObjectMethodA(JNIEnv* env,
1022 jobject obj, jclass clazz, jmethodID methodID, jvalue* args) {
1023 ScopedJniThreadState ts(env);
1024 JValue result = InvokeWithJValues(ts, obj, methodID, args);
1025 return AddLocalReference<jobject>(ts, result.l);
1026 }
1027
1028 static jboolean CallNonvirtualBooleanMethod(JNIEnv* env,
1029 jobject obj, jclass clazz, jmethodID methodID, ...) {
1030 ScopedJniThreadState ts(env);
1031 va_list ap;
1032 va_start(ap, methodID);
1033 JValue result = InvokeWithVarArgs(ts, obj, methodID, ap);
1034 va_end(ap);
1035 return result.z;
1036 }
1037
1038 static jboolean CallNonvirtualBooleanMethodV(JNIEnv* env,
1039 jobject obj, jclass clazz, jmethodID methodID, va_list args) {
1040 ScopedJniThreadState ts(env);
1041 return InvokeWithVarArgs(ts, obj, methodID, args).z;
1042 }
1043
1044 static jboolean CallNonvirtualBooleanMethodA(JNIEnv* env,
1045 jobject obj, jclass clazz, jmethodID methodID, jvalue* args) {
1046 ScopedJniThreadState ts(env);
1047 return InvokeWithJValues(ts, obj, methodID, args).z;
1048 }
1049
1050 static jbyte CallNonvirtualByteMethod(JNIEnv* env,
1051 jobject obj, jclass clazz, jmethodID methodID, ...) {
1052 ScopedJniThreadState ts(env);
1053 va_list ap;
1054 va_start(ap, methodID);
1055 JValue result = InvokeWithVarArgs(ts, obj, methodID, ap);
1056 va_end(ap);
1057 return result.b;
1058 }
1059
1060 static jbyte CallNonvirtualByteMethodV(JNIEnv* env,
1061 jobject obj, jclass clazz, jmethodID methodID, va_list args) {
1062 ScopedJniThreadState ts(env);
1063 return InvokeWithVarArgs(ts, obj, methodID, args).b;
1064 }
1065
1066 static jbyte CallNonvirtualByteMethodA(JNIEnv* env,
1067 jobject obj, jclass clazz, jmethodID methodID, jvalue* args) {
1068 ScopedJniThreadState ts(env);
1069 return InvokeWithJValues(ts, obj, methodID, args).b;
1070 }
1071
1072 static jchar CallNonvirtualCharMethod(JNIEnv* env,
1073 jobject obj, jclass clazz, jmethodID methodID, ...) {
1074 ScopedJniThreadState ts(env);
1075 va_list ap;
1076 va_start(ap, methodID);
1077 JValue result = InvokeWithVarArgs(ts, obj, methodID, ap);
1078 va_end(ap);
1079 return result.c;
1080 }
1081
1082 static jchar CallNonvirtualCharMethodV(JNIEnv* env,
1083 jobject obj, jclass clazz, jmethodID methodID, va_list args) {
1084 ScopedJniThreadState ts(env);
1085 return InvokeWithVarArgs(ts, obj, methodID, args).c;
1086 }
1087
1088 static jchar CallNonvirtualCharMethodA(JNIEnv* env,
1089 jobject obj, jclass clazz, jmethodID methodID, jvalue* args) {
1090 ScopedJniThreadState ts(env);
1091 return InvokeWithJValues(ts, obj, methodID, args).c;
1092 }
1093
1094 static jshort CallNonvirtualShortMethod(JNIEnv* env,
1095 jobject obj, jclass clazz, jmethodID methodID, ...) {
1096 ScopedJniThreadState ts(env);
1097 va_list ap;
1098 va_start(ap, methodID);
1099 JValue result = InvokeWithVarArgs(ts, obj, methodID, ap);
1100 va_end(ap);
1101 return result.s;
1102 }
1103
1104 static jshort CallNonvirtualShortMethodV(JNIEnv* env,
1105 jobject obj, jclass clazz, jmethodID methodID, va_list args) {
1106 ScopedJniThreadState ts(env);
1107 return InvokeWithVarArgs(ts, obj, methodID, args).s;
1108 }
1109
1110 static jshort CallNonvirtualShortMethodA(JNIEnv* env,
1111 jobject obj, jclass clazz, jmethodID methodID, jvalue* args) {
1112 ScopedJniThreadState ts(env);
1113 return InvokeWithJValues(ts, obj, methodID, args).s;
1114 }
1115
1116 static jint CallNonvirtualIntMethod(JNIEnv* env,
1117 jobject obj, jclass clazz, jmethodID methodID, ...) {
1118 ScopedJniThreadState ts(env);
1119 va_list ap;
1120 va_start(ap, methodID);
1121 JValue result = InvokeWithVarArgs(ts, obj, methodID, ap);
1122 va_end(ap);
1123 return result.i;
1124 }
1125
1126 static jint CallNonvirtualIntMethodV(JNIEnv* env,
1127 jobject obj, jclass clazz, jmethodID methodID, va_list args) {
1128 ScopedJniThreadState ts(env);
1129 return InvokeWithVarArgs(ts, obj, methodID, args).i;
1130 }
1131
1132 static jint CallNonvirtualIntMethodA(JNIEnv* env,
1133 jobject obj, jclass clazz, jmethodID methodID, jvalue* args) {
1134 ScopedJniThreadState ts(env);
1135 return InvokeWithJValues(ts, obj, methodID, args).i;
1136 }
1137
1138 static jlong CallNonvirtualLongMethod(JNIEnv* env,
1139 jobject obj, jclass clazz, jmethodID methodID, ...) {
1140 ScopedJniThreadState ts(env);
1141 va_list ap;
1142 va_start(ap, methodID);
1143 JValue result = InvokeWithVarArgs(ts, obj, methodID, ap);
1144 va_end(ap);
1145 return result.j;
1146 }
1147
1148 static jlong CallNonvirtualLongMethodV(JNIEnv* env,
1149 jobject obj, jclass clazz, jmethodID methodID, va_list args) {
1150 ScopedJniThreadState ts(env);
1151 return InvokeWithVarArgs(ts, obj, methodID, args).j;
1152 }
1153
1154 static jlong CallNonvirtualLongMethodA(JNIEnv* env,
1155 jobject obj, jclass clazz, jmethodID methodID, jvalue* args) {
1156 ScopedJniThreadState ts(env);
1157 return InvokeWithJValues(ts, obj, methodID, args).j;
1158 }
1159
1160 static jfloat CallNonvirtualFloatMethod(JNIEnv* env,
1161 jobject obj, jclass clazz, jmethodID methodID, ...) {
1162 ScopedJniThreadState ts(env);
1163 va_list ap;
1164 va_start(ap, methodID);
1165 JValue result = InvokeWithVarArgs(ts, obj, methodID, ap);
1166 va_end(ap);
1167 return result.f;
1168 }
1169
1170 static jfloat CallNonvirtualFloatMethodV(JNIEnv* env,
1171 jobject obj, jclass clazz, jmethodID methodID, va_list args) {
1172 ScopedJniThreadState ts(env);
1173 return InvokeWithVarArgs(ts, obj, methodID, args).f;
1174 }
1175
1176 static jfloat CallNonvirtualFloatMethodA(JNIEnv* env,
1177 jobject obj, jclass clazz, jmethodID methodID, jvalue* args) {
1178 ScopedJniThreadState ts(env);
1179 return InvokeWithJValues(ts, obj, methodID, args).f;
1180 }
1181
1182 static jdouble CallNonvirtualDoubleMethod(JNIEnv* env,
1183 jobject obj, jclass clazz, jmethodID methodID, ...) {
1184 ScopedJniThreadState ts(env);
1185 va_list ap;
1186 va_start(ap, methodID);
1187 JValue result = InvokeWithVarArgs(ts, obj, methodID, ap);
1188 va_end(ap);
1189 return result.d;
1190 }
1191
1192 static jdouble CallNonvirtualDoubleMethodV(JNIEnv* env,
1193 jobject obj, jclass clazz, jmethodID methodID, va_list args) {
1194 ScopedJniThreadState ts(env);
1195 return InvokeWithVarArgs(ts, obj, methodID, args).d;
1196 }
1197
1198 static jdouble CallNonvirtualDoubleMethodA(JNIEnv* env,
1199 jobject obj, jclass clazz, jmethodID methodID, jvalue* args) {
1200 ScopedJniThreadState ts(env);
1201 return InvokeWithJValues(ts, obj, methodID, args).d;
1202 }
1203
1204 static void CallNonvirtualVoidMethod(JNIEnv* env,
1205 jobject obj, jclass clazz, jmethodID methodID, ...) {
1206 ScopedJniThreadState ts(env);
1207 va_list ap;
1208 va_start(ap, methodID);
1209 InvokeWithVarArgs(ts, obj, methodID, ap);
1210 va_end(ap);
1211 }
1212
1213 static void CallNonvirtualVoidMethodV(JNIEnv* env,
1214 jobject obj, jclass clazz, jmethodID methodID, va_list args) {
1215 ScopedJniThreadState ts(env);
1216 InvokeWithVarArgs(ts, obj, methodID, args);
1217 }
1218
1219 static void CallNonvirtualVoidMethodA(JNIEnv* env,
1220 jobject obj, jclass clazz, jmethodID methodID, jvalue* args) {
1221 ScopedJniThreadState ts(env);
1222 InvokeWithJValues(ts, obj, methodID, args);
1223 }
1224
1225 static jfieldID GetFieldID(JNIEnv* env,
1226 jclass c, const char* name, const char* sig) {
1227 ScopedJniThreadState ts(env);
1228 return FindFieldID(ts, c, name, sig, false);
1229 }
Carl Shapiroea4dca82011-08-01 13:45:38 -07001230
1231
Elliott Hughescdf53122011-08-19 15:46:09 -07001232 static jfieldID GetStaticFieldID(JNIEnv* env,
1233 jclass c, const char* name, const char* sig) {
1234 ScopedJniThreadState ts(env);
1235 return FindFieldID(ts, c, name, sig, true);
1236 }
Carl Shapiroea4dca82011-08-01 13:45:38 -07001237
Elliott Hughescdf53122011-08-19 15:46:09 -07001238 static jobject GetObjectField(JNIEnv* env, jobject obj, jfieldID fieldID) {
1239 ScopedJniThreadState ts(env);
1240 UNIMPLEMENTED(FATAL);
1241 return NULL;
1242 }
Carl Shapiroea4dca82011-08-01 13:45:38 -07001243
Elliott Hughescdf53122011-08-19 15:46:09 -07001244 static jboolean GetBooleanField(JNIEnv* env, jobject obj, jfieldID fieldID) {
1245 ScopedJniThreadState ts(env);
1246 UNIMPLEMENTED(FATAL);
1247 return JNI_FALSE;
1248 }
1249
1250 static jbyte GetByteField(JNIEnv* env, jobject obj, jfieldID fieldID) {
1251 ScopedJniThreadState ts(env);
1252 UNIMPLEMENTED(FATAL);
1253 return 0;
1254 }
1255
1256 static jchar GetCharField(JNIEnv* env, jobject obj, jfieldID fieldID) {
1257 ScopedJniThreadState ts(env);
1258 UNIMPLEMENTED(FATAL);
1259 return 0;
1260 }
1261
1262 static jshort GetShortField(JNIEnv* env, jobject obj, jfieldID fieldID) {
1263 ScopedJniThreadState ts(env);
1264 UNIMPLEMENTED(FATAL);
1265 return 0;
1266 }
1267
1268 static jint GetIntField(JNIEnv* env, jobject obj, jfieldID fieldID) {
1269 ScopedJniThreadState ts(env);
1270 UNIMPLEMENTED(FATAL);
1271 return 0;
1272 }
1273
1274 static jlong GetLongField(JNIEnv* env, jobject obj, jfieldID fieldID) {
1275 ScopedJniThreadState ts(env);
1276 UNIMPLEMENTED(FATAL);
1277 return 0;
1278 }
1279
1280 static jfloat GetFloatField(JNIEnv* env, jobject obj, jfieldID fieldID) {
1281 ScopedJniThreadState ts(env);
1282 UNIMPLEMENTED(FATAL);
1283 return 0;
1284 }
1285
1286 static jdouble GetDoubleField(JNIEnv* env, jobject obj, jfieldID fieldID) {
1287 ScopedJniThreadState ts(env);
1288 UNIMPLEMENTED(FATAL);
1289 return 0;
1290 }
1291
1292 static void SetObjectField(JNIEnv* env, jobject obj, jfieldID fieldID, jobject val) {
1293 ScopedJniThreadState ts(env);
1294 UNIMPLEMENTED(FATAL);
1295 }
1296
1297 static void SetBooleanField(JNIEnv* env, jobject obj, jfieldID fieldID, jboolean val) {
1298 ScopedJniThreadState ts(env);
1299 UNIMPLEMENTED(FATAL);
1300 }
1301
1302 static void SetByteField(JNIEnv* env, jobject obj, jfieldID fieldID, jbyte val) {
1303 ScopedJniThreadState ts(env);
1304 UNIMPLEMENTED(FATAL);
1305 }
1306
1307 static void SetCharField(JNIEnv* env, jobject obj, jfieldID fieldID, jchar val) {
1308 ScopedJniThreadState ts(env);
1309 UNIMPLEMENTED(FATAL);
1310 }
1311
1312 static void SetShortField(JNIEnv* env, jobject obj, jfieldID fieldID, jshort val) {
1313 ScopedJniThreadState ts(env);
1314 UNIMPLEMENTED(FATAL);
1315 }
1316
1317 static void SetIntField(JNIEnv* env, jobject obj, jfieldID fieldID, jint val) {
1318 ScopedJniThreadState ts(env);
1319 UNIMPLEMENTED(FATAL);
1320 }
1321
1322 static void SetLongField(JNIEnv* env, jobject obj, jfieldID fieldID, jlong val) {
1323 ScopedJniThreadState ts(env);
1324 UNIMPLEMENTED(FATAL);
1325 }
1326
1327 static void SetFloatField(JNIEnv* env, jobject obj, jfieldID fieldID, jfloat val) {
1328 ScopedJniThreadState ts(env);
1329 UNIMPLEMENTED(FATAL);
1330 }
1331
1332 static void SetDoubleField(JNIEnv* env, jobject obj, jfieldID fieldID, jdouble val) {
1333 ScopedJniThreadState ts(env);
1334 UNIMPLEMENTED(FATAL);
1335 }
1336
1337 static jobject CallStaticObjectMethod(JNIEnv* env,
1338 jclass clazz, jmethodID methodID, ...) {
1339 ScopedJniThreadState ts(env);
1340 va_list ap;
1341 va_start(ap, methodID);
1342 JValue result = InvokeWithVarArgs(ts, NULL, methodID, ap);
1343 jobject local_result = AddLocalReference<jobject>(ts, result.l);
1344 va_end(ap);
1345 return local_result;
1346 }
1347
1348 static jobject CallStaticObjectMethodV(JNIEnv* env,
1349 jclass clazz, jmethodID methodID, va_list args) {
1350 ScopedJniThreadState ts(env);
1351 JValue result = InvokeWithVarArgs(ts, NULL, methodID, args);
1352 return AddLocalReference<jobject>(ts, result.l);
1353 }
1354
1355 static jobject CallStaticObjectMethodA(JNIEnv* env,
1356 jclass clazz, jmethodID methodID, jvalue* args) {
1357 ScopedJniThreadState ts(env);
1358 JValue result = InvokeWithJValues(ts, NULL, methodID, args);
1359 return AddLocalReference<jobject>(ts, result.l);
1360 }
1361
1362 static jboolean CallStaticBooleanMethod(JNIEnv* env,
1363 jclass clazz, jmethodID methodID, ...) {
1364 ScopedJniThreadState ts(env);
1365 va_list ap;
1366 va_start(ap, methodID);
1367 JValue result = InvokeWithVarArgs(ts, NULL, methodID, ap);
1368 va_end(ap);
1369 return result.z;
1370 }
1371
1372 static jboolean CallStaticBooleanMethodV(JNIEnv* env,
1373 jclass clazz, jmethodID methodID, va_list args) {
1374 ScopedJniThreadState ts(env);
1375 return InvokeWithVarArgs(ts, NULL, methodID, args).z;
1376 }
1377
1378 static jboolean CallStaticBooleanMethodA(JNIEnv* env,
1379 jclass clazz, jmethodID methodID, jvalue* args) {
1380 ScopedJniThreadState ts(env);
1381 return InvokeWithJValues(ts, NULL, methodID, args).z;
1382 }
1383
1384 static jbyte CallStaticByteMethod(JNIEnv* env, jclass clazz, jmethodID methodID, ...) {
1385 ScopedJniThreadState ts(env);
1386 va_list ap;
1387 va_start(ap, methodID);
1388 JValue result = InvokeWithVarArgs(ts, NULL, methodID, ap);
1389 va_end(ap);
1390 return result.b;
1391 }
1392
1393 static jbyte CallStaticByteMethodV(JNIEnv* env,
1394 jclass clazz, jmethodID methodID, va_list args) {
1395 ScopedJniThreadState ts(env);
1396 return InvokeWithVarArgs(ts, NULL, methodID, args).b;
1397 }
1398
1399 static jbyte CallStaticByteMethodA(JNIEnv* env,
1400 jclass clazz, jmethodID methodID, jvalue* args) {
1401 ScopedJniThreadState ts(env);
1402 return InvokeWithJValues(ts, NULL, methodID, args).b;
1403 }
1404
1405 static jchar CallStaticCharMethod(JNIEnv* env, jclass clazz, jmethodID methodID, ...) {
1406 ScopedJniThreadState ts(env);
1407 va_list ap;
1408 va_start(ap, methodID);
1409 JValue result = InvokeWithVarArgs(ts, NULL, methodID, ap);
1410 va_end(ap);
1411 return result.c;
1412 }
1413
1414 static jchar CallStaticCharMethodV(JNIEnv* env,
1415 jclass clazz, jmethodID methodID, va_list args) {
1416 ScopedJniThreadState ts(env);
1417 return InvokeWithVarArgs(ts, NULL, methodID, args).c;
1418 }
1419
1420 static jchar CallStaticCharMethodA(JNIEnv* env,
1421 jclass clazz, jmethodID methodID, jvalue* args) {
1422 ScopedJniThreadState ts(env);
1423 return InvokeWithJValues(ts, NULL, methodID, args).c;
1424 }
1425
1426 static jshort CallStaticShortMethod(JNIEnv* env, jclass clazz, jmethodID methodID, ...) {
1427 ScopedJniThreadState ts(env);
1428 va_list ap;
1429 va_start(ap, methodID);
1430 JValue result = InvokeWithVarArgs(ts, NULL, methodID, ap);
1431 va_end(ap);
1432 return result.s;
1433 }
1434
1435 static jshort CallStaticShortMethodV(JNIEnv* env,
1436 jclass clazz, jmethodID methodID, va_list args) {
1437 ScopedJniThreadState ts(env);
1438 return InvokeWithVarArgs(ts, NULL, methodID, args).s;
1439 }
1440
1441 static jshort CallStaticShortMethodA(JNIEnv* env,
1442 jclass clazz, jmethodID methodID, jvalue* args) {
1443 ScopedJniThreadState ts(env);
1444 return InvokeWithJValues(ts, NULL, methodID, args).s;
1445 }
1446
1447 static jint CallStaticIntMethod(JNIEnv* env, jclass clazz, jmethodID methodID, ...) {
1448 ScopedJniThreadState ts(env);
1449 va_list ap;
1450 va_start(ap, methodID);
1451 JValue result = InvokeWithVarArgs(ts, NULL, methodID, ap);
1452 va_end(ap);
1453 return result.i;
1454 }
1455
1456 static jint CallStaticIntMethodV(JNIEnv* env,
1457 jclass clazz, jmethodID methodID, va_list args) {
1458 ScopedJniThreadState ts(env);
1459 return InvokeWithVarArgs(ts, NULL, methodID, args).i;
1460 }
1461
1462 static jint CallStaticIntMethodA(JNIEnv* env,
1463 jclass clazz, jmethodID methodID, jvalue* args) {
1464 ScopedJniThreadState ts(env);
1465 return InvokeWithJValues(ts, NULL, methodID, args).i;
1466 }
1467
1468 static jlong CallStaticLongMethod(JNIEnv* env, jclass clazz, jmethodID methodID, ...) {
1469 ScopedJniThreadState ts(env);
1470 va_list ap;
1471 va_start(ap, methodID);
1472 JValue result = InvokeWithVarArgs(ts, NULL, methodID, ap);
1473 va_end(ap);
1474 return result.j;
1475 }
1476
1477 static jlong CallStaticLongMethodV(JNIEnv* env,
1478 jclass clazz, jmethodID methodID, va_list args) {
1479 ScopedJniThreadState ts(env);
1480 return InvokeWithVarArgs(ts, NULL, methodID, args).j;
1481 }
1482
1483 static jlong CallStaticLongMethodA(JNIEnv* env,
1484 jclass clazz, jmethodID methodID, jvalue* args) {
1485 ScopedJniThreadState ts(env);
1486 return InvokeWithJValues(ts, NULL, methodID, args).j;
1487 }
1488
1489 static jfloat CallStaticFloatMethod(JNIEnv* env, jclass cls, jmethodID methodID, ...) {
1490 ScopedJniThreadState ts(env);
1491 va_list ap;
1492 va_start(ap, methodID);
1493 JValue result = InvokeWithVarArgs(ts, NULL, methodID, ap);
1494 va_end(ap);
1495 return result.f;
1496 }
1497
1498 static jfloat CallStaticFloatMethodV(JNIEnv* env,
1499 jclass clazz, jmethodID methodID, va_list args) {
1500 ScopedJniThreadState ts(env);
1501 return InvokeWithVarArgs(ts, NULL, methodID, args).f;
1502 }
1503
1504 static jfloat CallStaticFloatMethodA(JNIEnv* env,
1505 jclass clazz, jmethodID methodID, jvalue* args) {
1506 ScopedJniThreadState ts(env);
1507 return InvokeWithJValues(ts, NULL, methodID, args).f;
1508 }
1509
1510 static jdouble CallStaticDoubleMethod(JNIEnv* env, jclass cls, jmethodID methodID, ...) {
1511 ScopedJniThreadState ts(env);
1512 va_list ap;
1513 va_start(ap, methodID);
1514 JValue result = InvokeWithVarArgs(ts, NULL, methodID, ap);
1515 va_end(ap);
1516 return result.d;
1517 }
1518
1519 static jdouble CallStaticDoubleMethodV(JNIEnv* env,
1520 jclass clazz, jmethodID methodID, va_list args) {
1521 ScopedJniThreadState ts(env);
1522 return InvokeWithVarArgs(ts, NULL, methodID, args).d;
1523 }
1524
1525 static jdouble CallStaticDoubleMethodA(JNIEnv* env,
1526 jclass clazz, jmethodID methodID, jvalue* args) {
1527 ScopedJniThreadState ts(env);
1528 return InvokeWithJValues(ts, NULL, methodID, args).d;
1529 }
1530
1531 static void CallStaticVoidMethod(JNIEnv* env, jclass cls, jmethodID methodID, ...) {
1532 ScopedJniThreadState ts(env);
1533 va_list ap;
1534 va_start(ap, methodID);
1535 InvokeWithVarArgs(ts, NULL, methodID, ap);
1536 va_end(ap);
1537 }
1538
1539 static void CallStaticVoidMethodV(JNIEnv* env,
1540 jclass cls, jmethodID methodID, va_list args) {
1541 ScopedJniThreadState ts(env);
1542 InvokeWithVarArgs(ts, NULL, methodID, args);
1543 }
1544
1545 static void CallStaticVoidMethodA(JNIEnv* env,
1546 jclass cls, jmethodID methodID, jvalue* args) {
1547 ScopedJniThreadState ts(env);
1548 InvokeWithJValues(ts, NULL, methodID, args);
1549 }
1550
1551 static jobject GetStaticObjectField(JNIEnv* env, jclass clazz, jfieldID fieldID) {
1552 ScopedJniThreadState ts(env);
1553 UNIMPLEMENTED(FATAL);
1554 return NULL;
1555 }
1556
1557 static jboolean GetStaticBooleanField(JNIEnv* env, jclass clazz, jfieldID fieldID) {
1558 ScopedJniThreadState ts(env);
1559 UNIMPLEMENTED(FATAL);
1560 return JNI_FALSE;
1561 }
1562
1563 static jbyte GetStaticByteField(JNIEnv* env, jclass clazz, jfieldID fieldID) {
1564 ScopedJniThreadState ts(env);
1565 UNIMPLEMENTED(FATAL);
1566 return 0;
1567 }
1568
1569 static jchar GetStaticCharField(JNIEnv* env, jclass clazz, jfieldID fieldID) {
1570 ScopedJniThreadState ts(env);
1571 UNIMPLEMENTED(FATAL);
1572 return 0;
1573 }
1574
1575 static jshort GetStaticShortField(JNIEnv* env, jclass clazz, jfieldID fieldID) {
1576 ScopedJniThreadState ts(env);
1577 UNIMPLEMENTED(FATAL);
1578 return 0;
1579 }
1580
1581 static jint GetStaticIntField(JNIEnv* env, jclass clazz, jfieldID fieldID) {
1582 ScopedJniThreadState ts(env);
1583 UNIMPLEMENTED(FATAL);
1584 return 0;
1585 }
1586
1587 static jlong GetStaticLongField(JNIEnv* env, jclass clazz, jfieldID fieldID) {
1588 ScopedJniThreadState ts(env);
1589 UNIMPLEMENTED(FATAL);
1590 return 0;
1591 }
1592
1593 static jfloat GetStaticFloatField(JNIEnv* env, jclass clazz, jfieldID fieldID) {
1594 ScopedJniThreadState ts(env);
1595 UNIMPLEMENTED(FATAL);
1596 return 0;
1597 }
1598
1599 static jdouble GetStaticDoubleField(JNIEnv* env, jclass clazz, jfieldID fieldID) {
1600 ScopedJniThreadState ts(env);
1601 UNIMPLEMENTED(FATAL);
1602 return 0;
1603 }
1604
1605 static void SetStaticObjectField(JNIEnv* env,
1606 jclass clazz, jfieldID fieldID, jobject value) {
1607 ScopedJniThreadState ts(env);
1608 UNIMPLEMENTED(FATAL);
1609 }
1610
1611 static void SetStaticBooleanField(JNIEnv* env,
1612 jclass clazz, jfieldID fieldID, jboolean value) {
1613 ScopedJniThreadState ts(env);
1614 UNIMPLEMENTED(FATAL);
1615 }
1616
1617 static void SetStaticByteField(JNIEnv* env,
1618 jclass clazz, jfieldID fieldID, jbyte value) {
1619 ScopedJniThreadState ts(env);
1620 UNIMPLEMENTED(FATAL);
1621 }
1622
1623 static void SetStaticCharField(JNIEnv* env,
1624 jclass clazz, jfieldID fieldID, jchar value) {
1625 ScopedJniThreadState ts(env);
1626 UNIMPLEMENTED(FATAL);
1627 }
1628
1629 static void SetStaticShortField(JNIEnv* env,
1630 jclass clazz, jfieldID fieldID, jshort value) {
1631 ScopedJniThreadState ts(env);
1632 UNIMPLEMENTED(FATAL);
1633 }
1634
1635 static void SetStaticIntField(JNIEnv* env,
1636 jclass clazz, jfieldID fieldID, jint value) {
1637 ScopedJniThreadState ts(env);
1638 UNIMPLEMENTED(FATAL);
1639 }
1640
1641 static void SetStaticLongField(JNIEnv* env,
1642 jclass clazz, jfieldID fieldID, jlong value) {
1643 ScopedJniThreadState ts(env);
1644 UNIMPLEMENTED(FATAL);
1645 }
1646
1647 static void SetStaticFloatField(JNIEnv* env,
1648 jclass clazz, jfieldID fieldID, jfloat value) {
1649 ScopedJniThreadState ts(env);
1650 UNIMPLEMENTED(FATAL);
1651 }
1652
1653 static void SetStaticDoubleField(JNIEnv* env,
1654 jclass clazz, jfieldID fieldID, jdouble value) {
1655 ScopedJniThreadState ts(env);
1656 UNIMPLEMENTED(FATAL);
1657 }
1658
1659 static jstring NewString(JNIEnv* env, const jchar* unicode, jsize len) {
1660 ScopedJniThreadState ts(env);
1661 UNIMPLEMENTED(FATAL);
1662 return NULL;
1663 }
1664
1665 static jsize GetStringLength(JNIEnv* env, jstring str) {
1666 ScopedJniThreadState ts(env);
1667 UNIMPLEMENTED(FATAL);
1668 return 0;
1669 }
1670
1671 static const jchar* GetStringChars(JNIEnv* env, jstring str, jboolean* isCopy) {
1672 ScopedJniThreadState ts(env);
1673 UNIMPLEMENTED(FATAL);
1674 return NULL;
1675 }
1676
1677 static void ReleaseStringChars(JNIEnv* env, jstring str, const jchar* chars) {
1678 ScopedJniThreadState ts(env);
1679 UNIMPLEMENTED(FATAL);
1680 }
1681
1682 static jstring NewStringUTF(JNIEnv* env, const char* utf) {
1683 ScopedJniThreadState ts(env);
1684 if (utf == NULL) {
1685 return NULL;
1686 }
1687 String* result = String::AllocFromModifiedUtf8(utf);
1688 return AddLocalReference<jstring>(ts, result);
1689 }
1690
1691 static jsize GetStringUTFLength(JNIEnv* env, jstring str) {
1692 ScopedJniThreadState ts(env);
1693 UNIMPLEMENTED(FATAL);
1694 return 0;
1695 }
1696
1697 static const char* GetStringUTFChars(JNIEnv* env, jstring str, jboolean* isCopy) {
1698 ScopedJniThreadState ts(env);
1699 UNIMPLEMENTED(FATAL);
1700 return NULL;
1701 }
1702
1703 static void ReleaseStringUTFChars(JNIEnv* env, jstring str, const char* chars) {
1704 ScopedJniThreadState ts(env);
1705 UNIMPLEMENTED(FATAL);
1706 }
1707
1708 static jsize GetArrayLength(JNIEnv* env, jarray array) {
1709 ScopedJniThreadState ts(env);
1710 UNIMPLEMENTED(FATAL);
1711 return 0;
1712 }
1713
1714 static jobject GetObjectArrayElement(JNIEnv* env, jobjectArray array, jsize index) {
1715 ScopedJniThreadState ts(env);
1716 UNIMPLEMENTED(FATAL);
1717 return NULL;
1718 }
1719
1720 static void SetObjectArrayElement(JNIEnv* env,
1721 jobjectArray java_array, jsize index, jobject java_value) {
1722 ScopedJniThreadState ts(env);
1723 ObjectArray<Object>* array = Decode<ObjectArray<Object>*>(ts, java_array);
1724 Object* value = Decode<Object*>(ts, java_value);
1725 array->Set(index, value);
1726 }
1727
1728 static jbooleanArray NewBooleanArray(JNIEnv* env, jsize length) {
1729 ScopedJniThreadState ts(env);
1730 return NewPrimitiveArray<jbooleanArray, BooleanArray>(ts, length);
1731 }
1732
1733 static jbyteArray NewByteArray(JNIEnv* env, jsize length) {
1734 ScopedJniThreadState ts(env);
1735 return NewPrimitiveArray<jbyteArray, ByteArray>(ts, length);
1736 }
1737
1738 static jcharArray NewCharArray(JNIEnv* env, jsize length) {
1739 ScopedJniThreadState ts(env);
1740 return NewPrimitiveArray<jcharArray, CharArray>(ts, length);
1741 }
1742
1743 static jdoubleArray NewDoubleArray(JNIEnv* env, jsize length) {
1744 ScopedJniThreadState ts(env);
1745 return NewPrimitiveArray<jdoubleArray, DoubleArray>(ts, length);
1746 }
1747
1748 static jfloatArray NewFloatArray(JNIEnv* env, jsize length) {
1749 ScopedJniThreadState ts(env);
1750 return NewPrimitiveArray<jfloatArray, FloatArray>(ts, length);
1751 }
1752
1753 static jintArray NewIntArray(JNIEnv* env, jsize length) {
1754 ScopedJniThreadState ts(env);
1755 return NewPrimitiveArray<jintArray, IntArray>(ts, length);
1756 }
1757
1758 static jlongArray NewLongArray(JNIEnv* env, jsize length) {
1759 ScopedJniThreadState ts(env);
1760 return NewPrimitiveArray<jlongArray, LongArray>(ts, length);
1761 }
1762
1763 static jobjectArray NewObjectArray(JNIEnv* env, jsize length, jclass element_jclass, jobject initial_element) {
1764 ScopedJniThreadState ts(env);
1765 CHECK_GE(length, 0); // TODO: ReportJniError
1766
1767 // Compute the array class corresponding to the given element class.
1768 Class* element_class = Decode<Class*>(ts, element_jclass);
1769 std::string descriptor;
1770 descriptor += "[";
Brian Carlstrom9cff8e12011-08-18 16:47:29 -07001771 descriptor += element_class->GetDescriptor()->ToModifiedUtf8();
Elliott Hughescdf53122011-08-19 15:46:09 -07001772
1773 // Find the class.
1774 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
1775 // TODO: need to get the appropriate ClassLoader.
1776 Class* array_class = class_linker->FindClass(descriptor, NULL);
1777 if (array_class == NULL) {
1778 return NULL;
1779 }
1780
1781 ObjectArray<Object>* result = ObjectArray<Object>::Alloc(array_class, length);
1782 CHECK(initial_element == NULL); // TODO: support initial_element
1783 return AddLocalReference<jobjectArray>(ts, result);
1784 }
1785
1786 static jshortArray NewShortArray(JNIEnv* env, jsize length) {
1787 ScopedJniThreadState ts(env);
1788 return NewPrimitiveArray<jshortArray, ShortArray>(ts, length);
1789 }
1790
1791 static jboolean* GetBooleanArrayElements(JNIEnv* env,
1792 jbooleanArray array, jboolean* isCopy) {
1793 ScopedJniThreadState ts(env);
1794 UNIMPLEMENTED(FATAL);
1795 return NULL;
1796 }
1797
1798 static jbyte* GetByteArrayElements(JNIEnv* env, jbyteArray array, jboolean* isCopy) {
1799 ScopedJniThreadState ts(env);
1800 UNIMPLEMENTED(FATAL);
1801 return NULL;
1802 }
1803
1804 static jchar* GetCharArrayElements(JNIEnv* env, jcharArray array, jboolean* isCopy) {
1805 ScopedJniThreadState ts(env);
1806 UNIMPLEMENTED(FATAL);
1807 return NULL;
1808 }
1809
1810 static jshort* GetShortArrayElements(JNIEnv* env,
1811 jshortArray array, jboolean* isCopy) {
1812 ScopedJniThreadState ts(env);
1813 UNIMPLEMENTED(FATAL);
1814 return NULL;
1815 }
1816
1817 static jint* GetIntArrayElements(JNIEnv* env, jintArray array, jboolean* isCopy) {
1818 ScopedJniThreadState ts(env);
1819 UNIMPLEMENTED(FATAL);
1820 return NULL;
1821 }
1822
1823 static jlong* GetLongArrayElements(JNIEnv* env, jlongArray array, jboolean* isCopy) {
1824 ScopedJniThreadState ts(env);
1825 UNIMPLEMENTED(FATAL);
1826 return NULL;
1827 }
1828
1829 static jfloat* GetFloatArrayElements(JNIEnv* env,
1830 jfloatArray array, jboolean* isCopy) {
1831 ScopedJniThreadState ts(env);
1832 UNIMPLEMENTED(FATAL);
1833 return NULL;
1834 }
1835
1836 static jdouble* GetDoubleArrayElements(JNIEnv* env,
1837 jdoubleArray array, jboolean* isCopy) {
1838 ScopedJniThreadState ts(env);
1839 UNIMPLEMENTED(FATAL);
1840 return NULL;
1841 }
1842
1843 static void ReleaseBooleanArrayElements(JNIEnv* env,
1844 jbooleanArray array, jboolean* elems, jint mode) {
1845 ScopedJniThreadState ts(env);
1846 UNIMPLEMENTED(FATAL);
1847 }
1848
1849 static void ReleaseByteArrayElements(JNIEnv* env,
1850 jbyteArray array, jbyte* elems, jint mode) {
1851 ScopedJniThreadState ts(env);
1852 UNIMPLEMENTED(FATAL);
1853 }
1854
1855 static void ReleaseCharArrayElements(JNIEnv* env,
1856 jcharArray array, jchar* elems, jint mode) {
1857 ScopedJniThreadState ts(env);
1858 UNIMPLEMENTED(FATAL);
1859 }
1860
1861 static void ReleaseShortArrayElements(JNIEnv* env,
1862 jshortArray array, jshort* elems, jint mode) {
1863 ScopedJniThreadState ts(env);
1864 UNIMPLEMENTED(FATAL);
1865 }
1866
1867 static void ReleaseIntArrayElements(JNIEnv* env,
1868 jintArray array, jint* elems, jint mode) {
1869 ScopedJniThreadState ts(env);
1870 UNIMPLEMENTED(FATAL);
1871 }
1872
1873 static void ReleaseLongArrayElements(JNIEnv* env,
1874 jlongArray array, jlong* elems, jint mode) {
1875 ScopedJniThreadState ts(env);
1876 UNIMPLEMENTED(FATAL);
1877 }
1878
1879 static void ReleaseFloatArrayElements(JNIEnv* env,
1880 jfloatArray array, jfloat* elems, jint mode) {
1881 ScopedJniThreadState ts(env);
1882 UNIMPLEMENTED(FATAL);
1883 }
1884
1885 static void ReleaseDoubleArrayElements(JNIEnv* env,
1886 jdoubleArray array, jdouble* elems, jint mode) {
1887 ScopedJniThreadState ts(env);
1888 UNIMPLEMENTED(FATAL);
1889 }
1890
1891 static void GetBooleanArrayRegion(JNIEnv* env,
1892 jbooleanArray array, jsize start, jsize l, jboolean* buf) {
1893 ScopedJniThreadState ts(env);
1894 UNIMPLEMENTED(FATAL);
1895 }
1896
1897 static void GetByteArrayRegion(JNIEnv* env,
1898 jbyteArray array, jsize start, jsize len, jbyte* buf) {
1899 ScopedJniThreadState ts(env);
1900 UNIMPLEMENTED(FATAL);
1901 }
1902
1903 static void GetCharArrayRegion(JNIEnv* env,
1904 jcharArray array, jsize start, jsize len, jchar* buf) {
1905 ScopedJniThreadState ts(env);
1906 UNIMPLEMENTED(FATAL);
1907 }
1908
1909 static void GetShortArrayRegion(JNIEnv* env,
1910 jshortArray array, jsize start, jsize len, jshort* buf) {
1911 ScopedJniThreadState ts(env);
1912 UNIMPLEMENTED(FATAL);
1913 }
1914
1915 static void GetIntArrayRegion(JNIEnv* env,
1916 jintArray array, jsize start, jsize len, jint* buf) {
1917 ScopedJniThreadState ts(env);
1918 UNIMPLEMENTED(FATAL);
1919 }
1920
1921 static void GetLongArrayRegion(JNIEnv* env,
1922 jlongArray array, jsize start, jsize len, jlong* buf) {
1923 ScopedJniThreadState ts(env);
1924 UNIMPLEMENTED(FATAL);
1925 }
1926
1927 static void GetFloatArrayRegion(JNIEnv* env,
1928 jfloatArray array, jsize start, jsize len, jfloat* buf) {
1929 ScopedJniThreadState ts(env);
1930 UNIMPLEMENTED(FATAL);
1931 }
1932
1933 static void GetDoubleArrayRegion(JNIEnv* env,
1934 jdoubleArray array, jsize start, jsize len, jdouble* buf) {
1935 ScopedJniThreadState ts(env);
1936 UNIMPLEMENTED(FATAL);
1937 }
1938
1939 static void SetBooleanArrayRegion(JNIEnv* env,
1940 jbooleanArray array, jsize start, jsize l, const jboolean* buf) {
1941 ScopedJniThreadState ts(env);
1942 UNIMPLEMENTED(FATAL);
1943 }
1944
1945 static void SetByteArrayRegion(JNIEnv* env,
1946 jbyteArray array, jsize start, jsize len, const jbyte* buf) {
1947 ScopedJniThreadState ts(env);
1948 UNIMPLEMENTED(FATAL);
1949 }
1950
1951 static void SetCharArrayRegion(JNIEnv* env,
1952 jcharArray array, jsize start, jsize len, const jchar* buf) {
1953 ScopedJniThreadState ts(env);
1954 UNIMPLEMENTED(FATAL);
1955 }
1956
1957 static void SetShortArrayRegion(JNIEnv* env,
1958 jshortArray array, jsize start, jsize len, const jshort* buf) {
1959 ScopedJniThreadState ts(env);
1960 UNIMPLEMENTED(FATAL);
1961 }
1962
1963 static void SetIntArrayRegion(JNIEnv* env,
1964 jintArray array, jsize start, jsize len, const jint* buf) {
1965 ScopedJniThreadState ts(env);
1966 UNIMPLEMENTED(FATAL);
1967 }
1968
1969 static void SetLongArrayRegion(JNIEnv* env,
1970 jlongArray array, jsize start, jsize len, const jlong* buf) {
1971 ScopedJniThreadState ts(env);
1972 UNIMPLEMENTED(FATAL);
1973 }
1974
1975 static void SetFloatArrayRegion(JNIEnv* env,
1976 jfloatArray array, jsize start, jsize len, const jfloat* buf) {
1977 ScopedJniThreadState ts(env);
1978 UNIMPLEMENTED(FATAL);
1979 }
1980
1981 static void SetDoubleArrayRegion(JNIEnv* env,
1982 jdoubleArray array, jsize start, jsize len, const jdouble* buf) {
1983 ScopedJniThreadState ts(env);
1984 UNIMPLEMENTED(FATAL);
1985 }
1986
1987 static jint RegisterNatives(JNIEnv* env,
1988 jclass clazz, const JNINativeMethod* methods, jint nMethods) {
1989 ScopedJniThreadState ts(env);
1990 Class* klass = Decode<Class*>(ts, clazz);
1991 for(int i = 0; i < nMethods; i++) {
1992 const char* name = methods[i].name;
1993 const char* sig = methods[i].signature;
1994
1995 if (*sig == '!') {
1996 // TODO: fast jni. it's too noisy to log all these.
1997 ++sig;
1998 }
1999
2000 Method* method = klass->FindDirectMethod(name, sig);
2001 if (method == NULL) {
2002 method = klass->FindVirtualMethod(name, sig);
2003 }
2004 if (method == NULL) {
2005 Thread* self = Thread::Current();
Brian Carlstrom9cff8e12011-08-18 16:47:29 -07002006 std::string class_name = klass->GetDescriptor()->ToModifiedUtf8();
Elliott Hughescdf53122011-08-19 15:46:09 -07002007 // TODO: pretty print method names through a single routine
2008 self->ThrowNewException("Ljava/lang/NoSuchMethodError;",
2009 "no method \"%s.%s%s\"",
2010 class_name.c_str(), name, sig);
2011 return JNI_ERR;
2012 } else if (!method->IsNative()) {
2013 Thread* self = Thread::Current();
Brian Carlstrom9cff8e12011-08-18 16:47:29 -07002014 std::string class_name = klass->GetDescriptor()->ToModifiedUtf8();
Elliott Hughescdf53122011-08-19 15:46:09 -07002015 // TODO: pretty print method names through a single routine
2016 self->ThrowNewException("Ljava/lang/NoSuchMethodError;",
2017 "method \"%s.%s%s\" is not native",
2018 class_name.c_str(), name, sig);
2019 return JNI_ERR;
2020 }
2021 method->RegisterNative(methods[i].fnPtr);
2022 }
2023 return JNI_OK;
2024 }
2025
2026 static jint UnregisterNatives(JNIEnv* env, jclass clazz) {
2027 ScopedJniThreadState ts(env);
2028 UNIMPLEMENTED(FATAL);
2029 return 0;
2030 }
2031
2032 static jint MonitorEnter(JNIEnv* env, jobject obj) {
2033 ScopedJniThreadState ts(env);
2034 UNIMPLEMENTED(WARNING);
2035 return 0;
2036 }
2037
2038 static jint MonitorExit(JNIEnv* env, jobject obj) {
2039 ScopedJniThreadState ts(env);
2040 UNIMPLEMENTED(WARNING);
2041 return 0;
2042 }
2043
2044 static jint GetJavaVM(JNIEnv* env, JavaVM** vm) {
2045 ScopedJniThreadState ts(env);
2046 Runtime* runtime = Runtime::Current();
2047 if (runtime != NULL) {
2048 *vm = reinterpret_cast<JavaVM*>(runtime->GetJavaVM());
2049 } else {
2050 *vm = NULL;
2051 }
2052 return (*vm != NULL) ? JNI_OK : JNI_ERR;
2053 }
2054
2055 static void GetStringRegion(JNIEnv* env,
2056 jstring str, jsize start, jsize len, jchar* buf) {
2057 ScopedJniThreadState ts(env);
2058 UNIMPLEMENTED(FATAL);
2059 }
2060
2061 static void GetStringUTFRegion(JNIEnv* env,
2062 jstring str, jsize start, jsize len, char* buf) {
2063 ScopedJniThreadState ts(env);
2064 UNIMPLEMENTED(FATAL);
2065 }
2066
2067 static void* GetPrimitiveArrayCritical(JNIEnv* env,
2068 jarray array, jboolean* isCopy) {
2069 ScopedJniThreadState ts(env);
2070 UNIMPLEMENTED(FATAL);
2071 return NULL;
2072 }
2073
2074 static void ReleasePrimitiveArrayCritical(JNIEnv* env,
2075 jarray array, void* carray, jint mode) {
2076 ScopedJniThreadState ts(env);
2077 UNIMPLEMENTED(FATAL);
2078 }
2079
2080 static const jchar* GetStringCritical(JNIEnv* env, jstring s, jboolean* isCopy) {
2081 ScopedJniThreadState ts(env);
2082 UNIMPLEMENTED(FATAL);
2083 return NULL;
2084 }
2085
2086 static void ReleaseStringCritical(JNIEnv* env, jstring s, const jchar* cstr) {
2087 ScopedJniThreadState ts(env);
2088 UNIMPLEMENTED(FATAL);
2089 }
2090
2091 static jboolean ExceptionCheck(JNIEnv* env) {
2092 ScopedJniThreadState ts(env);
2093 return ts.Self()->IsExceptionPending() ? JNI_TRUE : JNI_FALSE;
2094 }
2095
2096 static jobject NewDirectByteBuffer(JNIEnv* env, void* address, jlong capacity) {
2097 ScopedJniThreadState ts(env);
2098 UNIMPLEMENTED(FATAL);
2099 return NULL;
2100 }
2101
2102 static void* GetDirectBufferAddress(JNIEnv* env, jobject buf) {
2103 ScopedJniThreadState ts(env);
2104 UNIMPLEMENTED(FATAL);
2105 return NULL;
2106 }
2107
2108 static jlong GetDirectBufferCapacity(JNIEnv* env, jobject buf) {
2109 ScopedJniThreadState ts(env);
2110 UNIMPLEMENTED(FATAL);
2111 return 0;
2112 }
2113
2114 static jobjectRefType GetObjectRefType(JNIEnv* env, jobject jobj) {
2115 ScopedJniThreadState ts(env);
2116 UNIMPLEMENTED(FATAL);
2117 return JNIInvalidRefType;
2118 }
2119};
Carl Shapiroea4dca82011-08-01 13:45:38 -07002120
Elliott Hughes40ef99e2011-08-11 17:44:34 -07002121static const struct JNINativeInterface gNativeInterface = {
Carl Shapiroea4dca82011-08-01 13:45:38 -07002122 NULL, // reserved0.
2123 NULL, // reserved1.
2124 NULL, // reserved2.
2125 NULL, // reserved3.
Elliott Hughescdf53122011-08-19 15:46:09 -07002126 JNI::GetVersion,
2127 JNI::DefineClass,
2128 JNI::FindClass,
2129 JNI::FromReflectedMethod,
2130 JNI::FromReflectedField,
2131 JNI::ToReflectedMethod,
2132 JNI::GetSuperclass,
2133 JNI::IsAssignableFrom,
2134 JNI::ToReflectedField,
2135 JNI::Throw,
2136 JNI::ThrowNew,
2137 JNI::ExceptionOccurred,
2138 JNI::ExceptionDescribe,
2139 JNI::ExceptionClear,
2140 JNI::FatalError,
2141 JNI::PushLocalFrame,
2142 JNI::PopLocalFrame,
2143 JNI::NewGlobalRef,
2144 JNI::DeleteGlobalRef,
2145 JNI::DeleteLocalRef,
2146 JNI::IsSameObject,
2147 JNI::NewLocalRef,
2148 JNI::EnsureLocalCapacity,
2149 JNI::AllocObject,
2150 JNI::NewObject,
2151 JNI::NewObjectV,
2152 JNI::NewObjectA,
2153 JNI::GetObjectClass,
2154 JNI::IsInstanceOf,
2155 JNI::GetMethodID,
2156 JNI::CallObjectMethod,
2157 JNI::CallObjectMethodV,
2158 JNI::CallObjectMethodA,
2159 JNI::CallBooleanMethod,
2160 JNI::CallBooleanMethodV,
2161 JNI::CallBooleanMethodA,
2162 JNI::CallByteMethod,
2163 JNI::CallByteMethodV,
2164 JNI::CallByteMethodA,
2165 JNI::CallCharMethod,
2166 JNI::CallCharMethodV,
2167 JNI::CallCharMethodA,
2168 JNI::CallShortMethod,
2169 JNI::CallShortMethodV,
2170 JNI::CallShortMethodA,
2171 JNI::CallIntMethod,
2172 JNI::CallIntMethodV,
2173 JNI::CallIntMethodA,
2174 JNI::CallLongMethod,
2175 JNI::CallLongMethodV,
2176 JNI::CallLongMethodA,
2177 JNI::CallFloatMethod,
2178 JNI::CallFloatMethodV,
2179 JNI::CallFloatMethodA,
2180 JNI::CallDoubleMethod,
2181 JNI::CallDoubleMethodV,
2182 JNI::CallDoubleMethodA,
2183 JNI::CallVoidMethod,
2184 JNI::CallVoidMethodV,
2185 JNI::CallVoidMethodA,
2186 JNI::CallNonvirtualObjectMethod,
2187 JNI::CallNonvirtualObjectMethodV,
2188 JNI::CallNonvirtualObjectMethodA,
2189 JNI::CallNonvirtualBooleanMethod,
2190 JNI::CallNonvirtualBooleanMethodV,
2191 JNI::CallNonvirtualBooleanMethodA,
2192 JNI::CallNonvirtualByteMethod,
2193 JNI::CallNonvirtualByteMethodV,
2194 JNI::CallNonvirtualByteMethodA,
2195 JNI::CallNonvirtualCharMethod,
2196 JNI::CallNonvirtualCharMethodV,
2197 JNI::CallNonvirtualCharMethodA,
2198 JNI::CallNonvirtualShortMethod,
2199 JNI::CallNonvirtualShortMethodV,
2200 JNI::CallNonvirtualShortMethodA,
2201 JNI::CallNonvirtualIntMethod,
2202 JNI::CallNonvirtualIntMethodV,
2203 JNI::CallNonvirtualIntMethodA,
2204 JNI::CallNonvirtualLongMethod,
2205 JNI::CallNonvirtualLongMethodV,
2206 JNI::CallNonvirtualLongMethodA,
2207 JNI::CallNonvirtualFloatMethod,
2208 JNI::CallNonvirtualFloatMethodV,
2209 JNI::CallNonvirtualFloatMethodA,
2210 JNI::CallNonvirtualDoubleMethod,
2211 JNI::CallNonvirtualDoubleMethodV,
2212 JNI::CallNonvirtualDoubleMethodA,
2213 JNI::CallNonvirtualVoidMethod,
2214 JNI::CallNonvirtualVoidMethodV,
2215 JNI::CallNonvirtualVoidMethodA,
2216 JNI::GetFieldID,
2217 JNI::GetObjectField,
2218 JNI::GetBooleanField,
2219 JNI::GetByteField,
2220 JNI::GetCharField,
2221 JNI::GetShortField,
2222 JNI::GetIntField,
2223 JNI::GetLongField,
2224 JNI::GetFloatField,
2225 JNI::GetDoubleField,
2226 JNI::SetObjectField,
2227 JNI::SetBooleanField,
2228 JNI::SetByteField,
2229 JNI::SetCharField,
2230 JNI::SetShortField,
2231 JNI::SetIntField,
2232 JNI::SetLongField,
2233 JNI::SetFloatField,
2234 JNI::SetDoubleField,
2235 JNI::GetStaticMethodID,
2236 JNI::CallStaticObjectMethod,
2237 JNI::CallStaticObjectMethodV,
2238 JNI::CallStaticObjectMethodA,
2239 JNI::CallStaticBooleanMethod,
2240 JNI::CallStaticBooleanMethodV,
2241 JNI::CallStaticBooleanMethodA,
2242 JNI::CallStaticByteMethod,
2243 JNI::CallStaticByteMethodV,
2244 JNI::CallStaticByteMethodA,
2245 JNI::CallStaticCharMethod,
2246 JNI::CallStaticCharMethodV,
2247 JNI::CallStaticCharMethodA,
2248 JNI::CallStaticShortMethod,
2249 JNI::CallStaticShortMethodV,
2250 JNI::CallStaticShortMethodA,
2251 JNI::CallStaticIntMethod,
2252 JNI::CallStaticIntMethodV,
2253 JNI::CallStaticIntMethodA,
2254 JNI::CallStaticLongMethod,
2255 JNI::CallStaticLongMethodV,
2256 JNI::CallStaticLongMethodA,
2257 JNI::CallStaticFloatMethod,
2258 JNI::CallStaticFloatMethodV,
2259 JNI::CallStaticFloatMethodA,
2260 JNI::CallStaticDoubleMethod,
2261 JNI::CallStaticDoubleMethodV,
2262 JNI::CallStaticDoubleMethodA,
2263 JNI::CallStaticVoidMethod,
2264 JNI::CallStaticVoidMethodV,
2265 JNI::CallStaticVoidMethodA,
2266 JNI::GetStaticFieldID,
2267 JNI::GetStaticObjectField,
2268 JNI::GetStaticBooleanField,
2269 JNI::GetStaticByteField,
2270 JNI::GetStaticCharField,
2271 JNI::GetStaticShortField,
2272 JNI::GetStaticIntField,
2273 JNI::GetStaticLongField,
2274 JNI::GetStaticFloatField,
2275 JNI::GetStaticDoubleField,
2276 JNI::SetStaticObjectField,
2277 JNI::SetStaticBooleanField,
2278 JNI::SetStaticByteField,
2279 JNI::SetStaticCharField,
2280 JNI::SetStaticShortField,
2281 JNI::SetStaticIntField,
2282 JNI::SetStaticLongField,
2283 JNI::SetStaticFloatField,
2284 JNI::SetStaticDoubleField,
2285 JNI::NewString,
2286 JNI::GetStringLength,
2287 JNI::GetStringChars,
2288 JNI::ReleaseStringChars,
2289 JNI::NewStringUTF,
2290 JNI::GetStringUTFLength,
2291 JNI::GetStringUTFChars,
2292 JNI::ReleaseStringUTFChars,
2293 JNI::GetArrayLength,
2294 JNI::NewObjectArray,
2295 JNI::GetObjectArrayElement,
2296 JNI::SetObjectArrayElement,
2297 JNI::NewBooleanArray,
2298 JNI::NewByteArray,
2299 JNI::NewCharArray,
2300 JNI::NewShortArray,
2301 JNI::NewIntArray,
2302 JNI::NewLongArray,
2303 JNI::NewFloatArray,
2304 JNI::NewDoubleArray,
2305 JNI::GetBooleanArrayElements,
2306 JNI::GetByteArrayElements,
2307 JNI::GetCharArrayElements,
2308 JNI::GetShortArrayElements,
2309 JNI::GetIntArrayElements,
2310 JNI::GetLongArrayElements,
2311 JNI::GetFloatArrayElements,
2312 JNI::GetDoubleArrayElements,
2313 JNI::ReleaseBooleanArrayElements,
2314 JNI::ReleaseByteArrayElements,
2315 JNI::ReleaseCharArrayElements,
2316 JNI::ReleaseShortArrayElements,
2317 JNI::ReleaseIntArrayElements,
2318 JNI::ReleaseLongArrayElements,
2319 JNI::ReleaseFloatArrayElements,
2320 JNI::ReleaseDoubleArrayElements,
2321 JNI::GetBooleanArrayRegion,
2322 JNI::GetByteArrayRegion,
2323 JNI::GetCharArrayRegion,
2324 JNI::GetShortArrayRegion,
2325 JNI::GetIntArrayRegion,
2326 JNI::GetLongArrayRegion,
2327 JNI::GetFloatArrayRegion,
2328 JNI::GetDoubleArrayRegion,
2329 JNI::SetBooleanArrayRegion,
2330 JNI::SetByteArrayRegion,
2331 JNI::SetCharArrayRegion,
2332 JNI::SetShortArrayRegion,
2333 JNI::SetIntArrayRegion,
2334 JNI::SetLongArrayRegion,
2335 JNI::SetFloatArrayRegion,
2336 JNI::SetDoubleArrayRegion,
2337 JNI::RegisterNatives,
2338 JNI::UnregisterNatives,
2339 JNI::MonitorEnter,
2340 JNI::MonitorExit,
2341 JNI::GetJavaVM,
2342 JNI::GetStringRegion,
2343 JNI::GetStringUTFRegion,
2344 JNI::GetPrimitiveArrayCritical,
2345 JNI::ReleasePrimitiveArrayCritical,
2346 JNI::GetStringCritical,
2347 JNI::ReleaseStringCritical,
2348 JNI::NewWeakGlobalRef,
2349 JNI::DeleteWeakGlobalRef,
2350 JNI::ExceptionCheck,
2351 JNI::NewDirectByteBuffer,
2352 JNI::GetDirectBufferAddress,
2353 JNI::GetDirectBufferCapacity,
2354 JNI::GetObjectRefType,
Carl Shapiroea4dca82011-08-01 13:45:38 -07002355};
2356
Elliott Hughes6c1a3942011-08-17 15:00:06 -07002357static const size_t kMonitorsInitial = 32; // Arbitrary.
2358static const size_t kMonitorsMax = 4096; // Arbitrary sanity check.
2359
2360static const size_t kLocalsInitial = 64; // Arbitrary.
2361static const size_t kLocalsMax = 512; // Arbitrary sanity check.
Elliott Hughesbbd76712011-08-17 10:25:24 -07002362
Elliott Hughes515a5bc2011-08-17 11:08:34 -07002363JNIEnvExt::JNIEnvExt(Thread* self, bool check_jni)
Elliott Hughesbbd76712011-08-17 10:25:24 -07002364 : fns(&gNativeInterface),
2365 self(self),
Elliott Hughes515a5bc2011-08-17 11:08:34 -07002366 check_jni(check_jni),
Elliott Hughesbbd76712011-08-17 10:25:24 -07002367 critical(false),
Elliott Hughes6c1a3942011-08-17 15:00:06 -07002368 monitors("monitors", kMonitorsInitial, kMonitorsMax),
2369 locals(kLocalsInitial, kLocalsMax, kLocal) {
Elliott Hughes40ef99e2011-08-11 17:44:34 -07002370}
2371
Carl Shapiroea4dca82011-08-01 13:45:38 -07002372// JNI Invocation interface.
2373
Carl Shapiro2ed144c2011-07-26 16:52:08 -07002374extern "C" jint JNI_CreateJavaVM(JavaVM** p_vm, void** p_env, void* vm_args) {
2375 const JavaVMInitArgs* args = static_cast<JavaVMInitArgs*>(vm_args);
2376 if (args->version < JNI_VERSION_1_2) {
2377 return JNI_EVERSION;
2378 }
2379 Runtime::Options options;
2380 for (int i = 0; i < args->nOptions; ++i) {
2381 JavaVMOption* option = &args->options[i];
Carl Shapirofc322c72011-07-27 00:20:01 -07002382 options.push_back(std::make_pair(StringPiece(option->optionString),
2383 option->extraInfo));
Carl Shapiro2ed144c2011-07-26 16:52:08 -07002384 }
2385 bool ignore_unrecognized = args->ignoreUnrecognized;
Elliott Hughesf2682d52011-08-15 16:37:04 -07002386 Runtime* runtime = Runtime::Create(options, ignore_unrecognized);
Carl Shapiro2ed144c2011-07-26 16:52:08 -07002387 if (runtime == NULL) {
2388 return JNI_ERR;
2389 } else {
2390 *p_env = reinterpret_cast<JNIEnv*>(Thread::Current()->GetJniEnv());
Elliott Hughes0af55432011-08-17 18:37:28 -07002391 *p_vm = reinterpret_cast<JavaVM*>(runtime->GetJavaVM());
Carl Shapiro2ed144c2011-07-26 16:52:08 -07002392 return JNI_OK;
2393 }
2394}
2395
Elliott Hughesf2682d52011-08-15 16:37:04 -07002396extern "C" jint JNI_GetCreatedJavaVMs(JavaVM** vms, jsize, jsize* vm_count) {
Carl Shapiro2ed144c2011-07-26 16:52:08 -07002397 Runtime* runtime = Runtime::Current();
2398 if (runtime == NULL) {
Elliott Hughesf2682d52011-08-15 16:37:04 -07002399 *vm_count = 0;
Carl Shapiro2ed144c2011-07-26 16:52:08 -07002400 } else {
Elliott Hughesf2682d52011-08-15 16:37:04 -07002401 *vm_count = 1;
Elliott Hughes0af55432011-08-17 18:37:28 -07002402 vms[0] = reinterpret_cast<JavaVM*>(runtime->GetJavaVM());
Carl Shapiro2ed144c2011-07-26 16:52:08 -07002403 }
2404 return JNI_OK;
2405}
2406
2407// Historically unsupported.
2408extern "C" jint JNI_GetDefaultJavaVMInitArgs(void* vm_args) {
2409 return JNI_ERR;
2410}
2411
Elliott Hughescdf53122011-08-19 15:46:09 -07002412class JII {
2413 public:
2414 static jint DestroyJavaVM(JavaVM* vm) {
2415 if (vm == NULL) {
2416 return JNI_ERR;
2417 } else {
2418 JavaVMExt* raw_vm = reinterpret_cast<JavaVMExt*>(vm);
2419 delete raw_vm->runtime;
2420 return JNI_OK;
2421 }
Carl Shapiro2ed144c2011-07-26 16:52:08 -07002422 }
Carl Shapiro2ed144c2011-07-26 16:52:08 -07002423
Elliott Hughescdf53122011-08-19 15:46:09 -07002424 static jint AttachCurrentThread(JavaVM* vm, JNIEnv** p_env, void* thr_args) {
2425 if (vm == NULL || p_env == NULL) {
2426 return JNI_ERR;
2427 }
Elliott Hughesf2682d52011-08-15 16:37:04 -07002428 JavaVMExt* raw_vm = reinterpret_cast<JavaVMExt*>(vm);
2429 Runtime* runtime = raw_vm->runtime;
Elliott Hughescdf53122011-08-19 15:46:09 -07002430 const char* name = NULL;
2431 if (thr_args != NULL) {
2432 // TODO: check version
2433 name = static_cast<JavaVMAttachArgs*>(thr_args)->name;
2434 // TODO: thread group
2435 }
2436 bool success = runtime->AttachCurrentThread(name, p_env);
2437 if (!success) {
2438 return JNI_ERR;
2439 } else {
2440 return JNI_OK;
2441 }
2442 }
2443
2444 static jint AttachCurrentThreadAsDaemon(JavaVM* vm, JNIEnv** p_env, void* thr_args) {
2445 if (vm == NULL || p_env == NULL) {
2446 return JNI_ERR;
2447 }
2448 JavaVMExt* raw_vm = reinterpret_cast<JavaVMExt*>(vm);
2449 Runtime* runtime = raw_vm->runtime;
2450 const char* name = NULL;
2451 if (thr_args != NULL) {
2452 // TODO: check version
2453 name = static_cast<JavaVMAttachArgs*>(thr_args)->name;
2454 // TODO: thread group
2455 }
2456 bool success = runtime->AttachCurrentThreadAsDaemon(name, p_env);
2457 if (!success) {
2458 return JNI_ERR;
2459 } else {
2460 return JNI_OK;
2461 }
2462 }
2463
2464 static jint DetachCurrentThread(JavaVM* vm) {
2465 if (vm == NULL) {
2466 return JNI_ERR;
2467 } else {
2468 JavaVMExt* raw_vm = reinterpret_cast<JavaVMExt*>(vm);
2469 Runtime* runtime = raw_vm->runtime;
2470 runtime->DetachCurrentThread();
2471 return JNI_OK;
2472 }
2473 }
2474
2475 static jint GetEnv(JavaVM* vm, void** env, jint version) {
2476 if (version < JNI_VERSION_1_1 || version > JNI_VERSION_1_6) {
2477 return JNI_EVERSION;
2478 }
2479 if (vm == NULL || env == NULL) {
2480 return JNI_ERR;
2481 }
2482 Thread* thread = Thread::Current();
2483 if (thread == NULL) {
2484 *env = NULL;
2485 return JNI_EDETACHED;
2486 }
2487 *env = thread->GetJniEnv();
Carl Shapiro2ed144c2011-07-26 16:52:08 -07002488 return JNI_OK;
2489 }
Elliott Hughescdf53122011-08-19 15:46:09 -07002490};
Carl Shapiro2ed144c2011-07-26 16:52:08 -07002491
Elliott Hughesf2682d52011-08-15 16:37:04 -07002492struct JNIInvokeInterface gInvokeInterface = {
Carl Shapiroea4dca82011-08-01 13:45:38 -07002493 NULL, // reserved0
2494 NULL, // reserved1
2495 NULL, // reserved2
Elliott Hughescdf53122011-08-19 15:46:09 -07002496 JII::DestroyJavaVM,
2497 JII::AttachCurrentThread,
2498 JII::DetachCurrentThread,
2499 JII::GetEnv,
2500 JII::AttachCurrentThreadAsDaemon
Carl Shapiroea4dca82011-08-01 13:45:38 -07002501};
2502
Elliott Hughesbbd76712011-08-17 10:25:24 -07002503static const size_t kPinTableInitialSize = 16;
2504static const size_t kPinTableMaxSize = 1024;
2505
Elliott Hughes6c1a3942011-08-17 15:00:06 -07002506static const size_t kGlobalsInitial = 512; // Arbitrary.
2507static const size_t kGlobalsMax = 51200; // Arbitrary sanity check.
2508
2509static const size_t kWeakGlobalsInitial = 16; // Arbitrary.
2510static const size_t kWeakGlobalsMax = 51200; // Arbitrary sanity check.
2511
Elliott Hughes0af55432011-08-17 18:37:28 -07002512JavaVMExt::JavaVMExt(Runtime* runtime, bool check_jni, bool verbose_jni)
Elliott Hughesbbd76712011-08-17 10:25:24 -07002513 : fns(&gInvokeInterface),
2514 runtime(runtime),
Elliott Hughes515a5bc2011-08-17 11:08:34 -07002515 check_jni(check_jni),
Elliott Hughes0af55432011-08-17 18:37:28 -07002516 verbose_jni(verbose_jni),
Elliott Hughes6c1a3942011-08-17 15:00:06 -07002517 pin_table("pin table", kPinTableInitialSize, kPinTableMaxSize),
Elliott Hughes18c07532011-08-18 15:50:51 -07002518 globals_lock(Mutex::Create("JNI global reference table lock")),
Elliott Hughes6c1a3942011-08-17 15:00:06 -07002519 globals(kGlobalsInitial, kGlobalsMax, kGlobal),
Elliott Hughes18c07532011-08-18 15:50:51 -07002520 weak_globals_lock(Mutex::Create("JNI weak global reference table lock")),
Elliott Hughes6c1a3942011-08-17 15:00:06 -07002521 weak_globals(kWeakGlobalsInitial, kWeakGlobalsMax, kWeakGlobal) {
Elliott Hughesf2682d52011-08-15 16:37:04 -07002522}
2523
Elliott Hughesde69d7f2011-08-18 16:49:37 -07002524JavaVMExt::~JavaVMExt() {
2525 delete globals_lock;
2526 delete weak_globals_lock;
2527}
2528
Elliott Hughescdf53122011-08-19 15:46:09 -07002529/*
2530 * Load native code from the specified absolute pathname. Per the spec,
2531 * if we've already loaded a library with the specified pathname, we
2532 * return without doing anything.
2533 *
2534 * TODO? for better results we should absolutify the pathname. For fully
2535 * correct results we should stat to get the inode and compare that. The
2536 * existing implementation is fine so long as everybody is using
2537 * System.loadLibrary.
2538 *
2539 * The library will be associated with the specified class loader. The JNI
2540 * spec says we can't load the same library into more than one class loader.
2541 *
2542 * Returns "true" on success. On failure, sets *detail to a
2543 * human-readable description of the error or NULL if no detail is
2544 * available; ownership of the string is transferred to the caller.
2545 */
2546bool JavaVMExt::LoadNativeLibrary(const std::string& path, Object* class_loader, char** detail) {
2547 *detail = NULL;
2548
2549 // See if we've already loaded this library. If we have, and the class loader
2550 // matches, return successfully without doing anything.
2551 SharedLibrary* library = libraries[path];
2552 if (library != NULL) {
2553 if (library->GetClassLoader() != class_loader) {
2554 LOG(WARNING) << "Shared library \"" << path << "\" already opened by "
2555 << "ClassLoader " << library->GetClassLoader() << "; "
2556 << "can't open in " << class_loader;
2557 *detail = strdup("already opened by different ClassLoader");
2558 return false;
2559 }
2560 if (verbose_jni) {
2561 LOG(INFO) << "[Shared library \"" << path << "\" already loaded in "
2562 << "ClassLoader " << class_loader << "]";
2563 }
2564 if (!library->CheckOnLoadResult(this)) {
2565 *detail = strdup("JNI_OnLoad failed before");
2566 return false;
2567 }
2568 return true;
2569 }
2570
2571 // Open the shared library. Because we're using a full path, the system
2572 // doesn't have to search through LD_LIBRARY_PATH. (It may do so to
2573 // resolve this library's dependencies though.)
2574
2575 // Failures here are expected when java.library.path has several entries
2576 // and we have to hunt for the lib.
2577
2578 // The current version of the dynamic linker prints detailed information
2579 // about dlopen() failures. Some things to check if the message is
2580 // cryptic:
2581 // - make sure the library exists on the device
2582 // - verify that the right path is being opened (the debug log message
2583 // above can help with that)
2584 // - check to see if the library is valid (e.g. not zero bytes long)
2585 // - check config/prelink-linux-arm.map to ensure that the library
2586 // is listed and is not being overrun by the previous entry (if
2587 // loading suddenly stops working on a prelinked library, this is
2588 // a good one to check)
2589 // - write a trivial app that calls sleep() then dlopen(), attach
2590 // to it with "strace -p <pid>" while it sleeps, and watch for
2591 // attempts to open nonexistent dependent shared libs
2592
2593 // TODO: automate some of these checks!
2594
2595 // This can execute slowly for a large library on a busy system, so we
2596 // want to switch from RUNNING to VMWAIT while it executes. This allows
2597 // the GC to ignore us.
2598 Thread* self = Thread::Current();
2599 Thread::State old_state = self->GetState();
2600 self->SetState(Thread::kWaiting); // TODO: VMWAIT
2601 void* handle = dlopen(path.c_str(), RTLD_LAZY);
2602 self->SetState(old_state);
2603
2604 if (verbose_jni) {
2605 LOG(INFO) << "[Call to dlopen(\"" << path << "\") returned " << handle << "]";
2606 }
2607
2608 if (handle == NULL) {
2609 *detail = strdup(dlerror());
2610 return false;
2611 }
2612
2613 // Create a new entry.
2614 library = new SharedLibrary(path, handle, class_loader);
2615 UNIMPLEMENTED(ERROR) << "missing pthread_cond_init";
2616 // pthread_cond_init(&library->onLoadCond, NULL);
2617
2618 libraries[path] = library;
2619
2620 // if (pNewEntry != pActualEntry) {
2621 // LOG(INFO) << "WOW: we lost a race to add a shared library (\"" << path << "\" ClassLoader=" << class_loader <<")";
2622 // freeSharedLibEntry(pNewEntry);
2623 // return CheckOnLoadResult(this, pActualEntry);
2624 // } else
2625 {
2626 if (verbose_jni) {
2627 LOG(INFO) << "[Added shared library \"" << path << "\" for ClassLoader " << class_loader << "]";
2628 }
2629
2630 bool result = true;
2631 void* sym = dlsym(handle, "JNI_OnLoad");
2632 if (sym == NULL) {
2633 if (verbose_jni) {
2634 LOG(INFO) << "[No JNI_OnLoad found in \"" << path << "\"]";
2635 }
2636 } else {
2637 // Call JNI_OnLoad. We have to override the current class
2638 // loader, which will always be "null" since the stuff at the
2639 // top of the stack is around Runtime.loadLibrary(). (See
2640 // the comments in the JNI FindClass function.)
2641 UNIMPLEMENTED(WARNING) << "need to override current class loader";
2642 typedef int (*JNI_OnLoadFn)(JavaVM*, void*);
2643 JNI_OnLoadFn jni_on_load = reinterpret_cast<JNI_OnLoadFn>(sym);
2644 //Object* prevOverride = self->classLoaderOverride;
2645 //self->classLoaderOverride = classLoader;
2646
2647 old_state = self->GetState();
2648 self->SetState(Thread::kNative);
2649 if (verbose_jni) {
2650 LOG(INFO) << "[Calling JNI_OnLoad in \"" << path << "\"]";
2651 }
2652 int version = (*jni_on_load)(reinterpret_cast<JavaVM*>(this), NULL);
2653 self->SetState(old_state);
2654
2655 UNIMPLEMENTED(WARNING) << "need to restore current class loader";
2656 //self->classLoaderOverride = prevOverride;
2657
2658 if (version != JNI_VERSION_1_2 &&
2659 version != JNI_VERSION_1_4 &&
2660 version != JNI_VERSION_1_6) {
2661 LOG(WARNING) << "JNI_OnLoad in \"" << path << "\" returned "
2662 << "bad version: " << version;
2663 // It's unwise to call dlclose() here, but we can mark it
2664 // as bad and ensure that future load attempts will fail.
2665 // We don't know how far JNI_OnLoad got, so there could
2666 // be some partially-initialized stuff accessible through
2667 // newly-registered native method calls. We could try to
2668 // unregister them, but that doesn't seem worthwhile.
2669 result = false;
2670 } else {
2671 if (verbose_jni) {
2672 LOG(INFO) << "[Returned " << (result ? "successfully" : "failure")
2673 << " from JNI_OnLoad in \"" << path << "\"]";
2674 }
2675 }
2676 }
2677
2678 library->SetResult(result);
2679 return result;
2680 }
2681}
2682
Ian Rogersdf20fe02011-07-20 20:34:16 -07002683} // namespace art