blob: 1444d9762a862d10e2ff8d8ad014cde7c787713e [file] [log] [blame]
Ian Rogers68d8b422014-07-17 11:09:10 -07001/*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "jni_internal.h"
18
19#include <dlfcn.h>
20
21#include "base/mutex.h"
22#include "base/stl_util.h"
23#include "check_jni.h"
24#include "indirect_reference_table-inl.h"
25#include "mirror/art_method.h"
26#include "mirror/class-inl.h"
27#include "mirror/class_loader.h"
Calin Juravlec8423522014-08-12 20:55:20 +010028#include "nativebridge/native_bridge.h"
Ian Rogers68d8b422014-07-17 11:09:10 -070029#include "java_vm_ext.h"
30#include "parsed_options.h"
Ian Rogersc0542af2014-09-03 16:16:56 -070031#include "runtime-inl.h"
Ian Rogers68d8b422014-07-17 11:09:10 -070032#include "ScopedLocalRef.h"
33#include "scoped_thread_state_change.h"
34#include "thread-inl.h"
35#include "thread_list.h"
36
37namespace art {
38
Ian Rogers68d8b422014-07-17 11:09:10 -070039static size_t gGlobalsInitial = 512; // Arbitrary.
40static size_t gGlobalsMax = 51200; // Arbitrary sanity check. (Must fit in 16 bits.)
41
42static const size_t kWeakGlobalsInitial = 16; // Arbitrary.
43static const size_t kWeakGlobalsMax = 51200; // Arbitrary sanity check. (Must fit in 16 bits.)
44
45static bool IsBadJniVersion(int version) {
46 // We don't support JNI_VERSION_1_1. These are the only other valid versions.
47 return version != JNI_VERSION_1_2 && version != JNI_VERSION_1_4 && version != JNI_VERSION_1_6;
48}
49
50class SharedLibrary {
51 public:
52 SharedLibrary(JNIEnv* env, Thread* self, const std::string& path, void* handle,
53 jobject class_loader)
54 : path_(path),
55 handle_(handle),
56 needs_native_bridge_(false),
57 class_loader_(env->NewGlobalRef(class_loader)),
58 jni_on_load_lock_("JNI_OnLoad lock"),
59 jni_on_load_cond_("JNI_OnLoad condition variable", jni_on_load_lock_),
60 jni_on_load_thread_id_(self->GetThreadId()),
61 jni_on_load_result_(kPending) {
62 }
63
64 ~SharedLibrary() {
65 Thread* self = Thread::Current();
66 if (self != nullptr) {
67 self->GetJniEnv()->DeleteGlobalRef(class_loader_);
68 }
69 }
70
71 jobject GetClassLoader() const {
72 return class_loader_;
73 }
74
75 const std::string& GetPath() const {
76 return path_;
77 }
78
79 /*
80 * Check the result of an earlier call to JNI_OnLoad on this library.
81 * If the call has not yet finished in another thread, wait for it.
82 */
83 bool CheckOnLoadResult()
84 LOCKS_EXCLUDED(jni_on_load_lock_) {
85 Thread* self = Thread::Current();
86 bool okay;
87 {
88 MutexLock mu(self, jni_on_load_lock_);
89
90 if (jni_on_load_thread_id_ == self->GetThreadId()) {
91 // Check this so we don't end up waiting for ourselves. We need to return "true" so the
92 // caller can continue.
93 LOG(INFO) << *self << " recursive attempt to load library " << "\"" << path_ << "\"";
94 okay = true;
95 } else {
96 while (jni_on_load_result_ == kPending) {
97 VLOG(jni) << "[" << *self << " waiting for \"" << path_ << "\" " << "JNI_OnLoad...]";
98 jni_on_load_cond_.Wait(self);
99 }
100
101 okay = (jni_on_load_result_ == kOkay);
102 VLOG(jni) << "[Earlier JNI_OnLoad for \"" << path_ << "\" "
103 << (okay ? "succeeded" : "failed") << "]";
104 }
105 }
106 return okay;
107 }
108
109 void SetResult(bool result) LOCKS_EXCLUDED(jni_on_load_lock_) {
110 Thread* self = Thread::Current();
111 MutexLock mu(self, jni_on_load_lock_);
112
113 jni_on_load_result_ = result ? kOkay : kFailed;
114 jni_on_load_thread_id_ = 0;
115
116 // Broadcast a wakeup to anybody sleeping on the condition variable.
117 jni_on_load_cond_.Broadcast(self);
118 }
119
120 void SetNeedsNativeBridge() {
121 needs_native_bridge_ = true;
122 }
123
124 bool NeedsNativeBridge() const {
125 return needs_native_bridge_;
126 }
127
128 void* FindSymbol(const std::string& symbol_name) {
129 return dlsym(handle_, symbol_name.c_str());
130 }
131
132 void* FindSymbolWithNativeBridge(const std::string& symbol_name, const char* shorty) {
133 CHECK(NeedsNativeBridge());
134
135 uint32_t len = 0;
Calin Juravlec8423522014-08-12 20:55:20 +0100136 return android::NativeBridgeGetTrampoline(handle_, symbol_name.c_str(), shorty, len);
Ian Rogers68d8b422014-07-17 11:09:10 -0700137 }
138
139 private:
140 enum JNI_OnLoadState {
141 kPending,
142 kFailed,
143 kOkay,
144 };
145
146 // Path to library "/system/lib/libjni.so".
147 const std::string path_;
148
149 // The void* returned by dlopen(3).
150 void* const handle_;
151
152 // True if a native bridge is required.
153 bool needs_native_bridge_;
154
155 // The ClassLoader this library is associated with, a global JNI reference that is
156 // created/deleted with the scope of the library.
157 const jobject class_loader_;
158
159 // Guards remaining items.
160 Mutex jni_on_load_lock_ DEFAULT_MUTEX_ACQUIRED_AFTER;
161 // Wait for JNI_OnLoad in other thread.
162 ConditionVariable jni_on_load_cond_ GUARDED_BY(jni_on_load_lock_);
163 // Recursive invocation guard.
164 uint32_t jni_on_load_thread_id_ GUARDED_BY(jni_on_load_lock_);
165 // Result of earlier JNI_OnLoad call.
166 JNI_OnLoadState jni_on_load_result_ GUARDED_BY(jni_on_load_lock_);
167};
168
169// This exists mainly to keep implementation details out of the header file.
170class Libraries {
171 public:
172 Libraries() {
173 }
174
175 ~Libraries() {
176 STLDeleteValues(&libraries_);
177 }
178
179 void Dump(std::ostream& os) const {
180 bool first = true;
181 for (const auto& library : libraries_) {
182 if (!first) {
183 os << ' ';
184 }
185 first = false;
186 os << library.first;
187 }
188 }
189
190 size_t size() const {
191 return libraries_.size();
192 }
193
194 SharedLibrary* Get(const std::string& path) {
195 auto it = libraries_.find(path);
196 return (it == libraries_.end()) ? nullptr : it->second;
197 }
198
199 void Put(const std::string& path, SharedLibrary* library) {
200 libraries_.Put(path, library);
201 }
202
203 // See section 11.3 "Linking Native Methods" of the JNI spec.
204 void* FindNativeMethod(mirror::ArtMethod* m, std::string& detail)
205 EXCLUSIVE_LOCKS_REQUIRED(Locks::jni_libraries_lock_)
206 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
207 std::string jni_short_name(JniShortName(m));
208 std::string jni_long_name(JniLongName(m));
209 const mirror::ClassLoader* declaring_class_loader = m->GetDeclaringClass()->GetClassLoader();
210 ScopedObjectAccessUnchecked soa(Thread::Current());
211 for (const auto& lib : libraries_) {
212 SharedLibrary* library = lib.second;
213 if (soa.Decode<mirror::ClassLoader*>(library->GetClassLoader()) != declaring_class_loader) {
214 // We only search libraries loaded by the appropriate ClassLoader.
215 continue;
216 }
217 // Try the short name then the long name...
218 void* fn;
219 if (library->NeedsNativeBridge()) {
220 const char* shorty = m->GetShorty();
221 fn = library->FindSymbolWithNativeBridge(jni_short_name, shorty);
222 if (fn == nullptr) {
223 fn = library->FindSymbolWithNativeBridge(jni_long_name, shorty);
224 }
225 } else {
226 fn = library->FindSymbol(jni_short_name);
227 if (fn == nullptr) {
228 fn = library->FindSymbol(jni_long_name);
229 }
230 }
231 if (fn == nullptr) {
232 fn = library->FindSymbol(jni_long_name);
233 }
234 if (fn != nullptr) {
235 VLOG(jni) << "[Found native code for " << PrettyMethod(m)
236 << " in \"" << library->GetPath() << "\"]";
237 return fn;
238 }
239 }
240 detail += "No implementation found for ";
241 detail += PrettyMethod(m);
242 detail += " (tried " + jni_short_name + " and " + jni_long_name + ")";
243 LOG(ERROR) << detail;
244 return nullptr;
245 }
246
247 private:
Mathieu Chartierbad02672014-08-25 13:08:22 -0700248 AllocationTrackingSafeMap<std::string, SharedLibrary*, kAllocatorTagJNILibrarires> libraries_;
Ian Rogers68d8b422014-07-17 11:09:10 -0700249};
250
251
252class JII {
253 public:
254 static jint DestroyJavaVM(JavaVM* vm) {
255 if (vm == nullptr) {
256 return JNI_ERR;
257 }
258 JavaVMExt* raw_vm = reinterpret_cast<JavaVMExt*>(vm);
259 delete raw_vm->GetRuntime();
260 return JNI_OK;
261 }
262
263 static jint AttachCurrentThread(JavaVM* vm, JNIEnv** p_env, void* thr_args) {
264 return AttachCurrentThreadInternal(vm, p_env, thr_args, false);
265 }
266
267 static jint AttachCurrentThreadAsDaemon(JavaVM* vm, JNIEnv** p_env, void* thr_args) {
268 return AttachCurrentThreadInternal(vm, p_env, thr_args, true);
269 }
270
271 static jint DetachCurrentThread(JavaVM* vm) {
272 if (vm == nullptr || Thread::Current() == nullptr) {
273 return JNI_ERR;
274 }
275 JavaVMExt* raw_vm = reinterpret_cast<JavaVMExt*>(vm);
276 Runtime* runtime = raw_vm->GetRuntime();
277 runtime->DetachCurrentThread();
278 return JNI_OK;
279 }
280
281 static jint GetEnv(JavaVM* vm, void** env, jint version) {
282 // GetEnv always returns a JNIEnv* for the most current supported JNI version,
283 // and unlike other calls that take a JNI version doesn't care if you supply
284 // JNI_VERSION_1_1, which we don't otherwise support.
285 if (IsBadJniVersion(version) && version != JNI_VERSION_1_1) {
286 LOG(ERROR) << "Bad JNI version passed to GetEnv: " << version;
287 return JNI_EVERSION;
288 }
289 if (vm == nullptr || env == nullptr) {
290 return JNI_ERR;
291 }
292 Thread* thread = Thread::Current();
293 if (thread == nullptr) {
294 *env = nullptr;
295 return JNI_EDETACHED;
296 }
297 *env = thread->GetJniEnv();
298 return JNI_OK;
299 }
300
301 private:
302 static jint AttachCurrentThreadInternal(JavaVM* vm, JNIEnv** p_env, void* raw_args, bool as_daemon) {
303 if (vm == nullptr || p_env == nullptr) {
304 return JNI_ERR;
305 }
306
307 // Return immediately if we're already attached.
308 Thread* self = Thread::Current();
309 if (self != nullptr) {
310 *p_env = self->GetJniEnv();
311 return JNI_OK;
312 }
313
314 Runtime* runtime = reinterpret_cast<JavaVMExt*>(vm)->GetRuntime();
315
316 // No threads allowed in zygote mode.
317 if (runtime->IsZygote()) {
318 LOG(ERROR) << "Attempt to attach a thread in the zygote";
319 return JNI_ERR;
320 }
321
322 JavaVMAttachArgs* args = static_cast<JavaVMAttachArgs*>(raw_args);
323 const char* thread_name = nullptr;
324 jobject thread_group = nullptr;
325 if (args != nullptr) {
326 if (IsBadJniVersion(args->version)) {
327 LOG(ERROR) << "Bad JNI version passed to "
328 << (as_daemon ? "AttachCurrentThreadAsDaemon" : "AttachCurrentThread") << ": "
329 << args->version;
330 return JNI_EVERSION;
331 }
332 thread_name = args->name;
333 thread_group = args->group;
334 }
335
336 if (!runtime->AttachCurrentThread(thread_name, as_daemon, thread_group, !runtime->IsCompiler())) {
337 *p_env = nullptr;
338 return JNI_ERR;
339 } else {
340 *p_env = Thread::Current()->GetJniEnv();
341 return JNI_OK;
342 }
343 }
344};
345
346const JNIInvokeInterface gJniInvokeInterface = {
347 nullptr, // reserved0
348 nullptr, // reserved1
349 nullptr, // reserved2
350 JII::DestroyJavaVM,
351 JII::AttachCurrentThread,
352 JII::DetachCurrentThread,
353 JII::GetEnv,
354 JII::AttachCurrentThreadAsDaemon
355};
356
357JavaVMExt::JavaVMExt(Runtime* runtime, ParsedOptions* options)
358 : runtime_(runtime),
359 check_jni_abort_hook_(nullptr),
360 check_jni_abort_hook_data_(nullptr),
361 check_jni_(false), // Initialized properly in the constructor body below.
362 force_copy_(options->force_copy_),
363 tracing_enabled_(!options->jni_trace_.empty() || VLOG_IS_ON(third_party_jni)),
364 trace_(options->jni_trace_),
Ian Rogers68d8b422014-07-17 11:09:10 -0700365 globals_lock_("JNI global reference table lock"),
366 globals_(gGlobalsInitial, gGlobalsMax, kGlobal),
367 libraries_(new Libraries),
368 unchecked_functions_(&gJniInvokeInterface),
369 weak_globals_lock_("JNI weak global reference table lock"),
370 weak_globals_(kWeakGlobalsInitial, kWeakGlobalsMax, kWeakGlobal),
371 allow_new_weak_globals_(true),
372 weak_globals_add_condition_("weak globals add condition", weak_globals_lock_) {
373 functions = unchecked_functions_;
374 if (options->check_jni_) {
375 SetCheckJniEnabled(true);
376 }
377}
378
379JavaVMExt::~JavaVMExt() {
380}
381
382void JavaVMExt::JniAbort(const char* jni_function_name, const char* msg) {
383 Thread* self = Thread::Current();
384 ScopedObjectAccess soa(self);
385 mirror::ArtMethod* current_method = self->GetCurrentMethod(nullptr);
386
387 std::ostringstream os;
388 os << "JNI DETECTED ERROR IN APPLICATION: " << msg;
389
390 if (jni_function_name != nullptr) {
391 os << "\n in call to " << jni_function_name;
392 }
393 // TODO: is this useful given that we're about to dump the calling thread's stack?
394 if (current_method != nullptr) {
395 os << "\n from " << PrettyMethod(current_method);
396 }
397 os << "\n";
398 self->Dump(os);
399
400 if (check_jni_abort_hook_ != nullptr) {
401 check_jni_abort_hook_(check_jni_abort_hook_data_, os.str());
402 } else {
403 // Ensure that we get a native stack trace for this thread.
404 self->TransitionFromRunnableToSuspended(kNative);
405 LOG(FATAL) << os.str();
406 self->TransitionFromSuspendedToRunnable(); // Unreachable, keep annotalysis happy.
407 }
408}
409
410void JavaVMExt::JniAbortV(const char* jni_function_name, const char* fmt, va_list ap) {
411 std::string msg;
412 StringAppendV(&msg, fmt, ap);
413 JniAbort(jni_function_name, msg.c_str());
414}
415
416void JavaVMExt::JniAbortF(const char* jni_function_name, const char* fmt, ...) {
417 va_list args;
418 va_start(args, fmt);
419 JniAbortV(jni_function_name, fmt, args);
420 va_end(args);
421}
422
423bool JavaVMExt::ShouldTrace(mirror::ArtMethod* method) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
424 // Fast where no tracing is enabled.
425 if (trace_.empty() && !VLOG_IS_ON(third_party_jni)) {
426 return false;
427 }
428 // Perform checks based on class name.
429 StringPiece class_name(method->GetDeclaringClassDescriptor());
430 if (!trace_.empty() && class_name.find(trace_) != std::string::npos) {
431 return true;
432 }
433 if (!VLOG_IS_ON(third_party_jni)) {
434 return false;
435 }
436 // Return true if we're trying to log all third-party JNI activity and 'method' doesn't look
437 // like part of Android.
438 static const char* gBuiltInPrefixes[] = {
439 "Landroid/",
440 "Lcom/android/",
441 "Lcom/google/android/",
442 "Ldalvik/",
443 "Ljava/",
444 "Ljavax/",
445 "Llibcore/",
446 "Lorg/apache/harmony/",
447 };
448 for (size_t i = 0; i < arraysize(gBuiltInPrefixes); ++i) {
449 if (class_name.starts_with(gBuiltInPrefixes[i])) {
450 return false;
451 }
452 }
453 return true;
454}
455
456jobject JavaVMExt::AddGlobalRef(Thread* self, mirror::Object* obj) {
457 // Check for null after decoding the object to handle cleared weak globals.
458 if (obj == nullptr) {
459 return nullptr;
460 }
461 WriterMutexLock mu(self, globals_lock_);
462 IndirectRef ref = globals_.Add(IRT_FIRST_SEGMENT, obj);
463 return reinterpret_cast<jobject>(ref);
464}
465
466jweak JavaVMExt::AddWeakGlobalRef(Thread* self, mirror::Object* obj) {
467 if (obj == nullptr) {
468 return nullptr;
469 }
470 MutexLock mu(self, weak_globals_lock_);
471 while (UNLIKELY(!allow_new_weak_globals_)) {
472 weak_globals_add_condition_.WaitHoldingLocks(self);
473 }
474 IndirectRef ref = weak_globals_.Add(IRT_FIRST_SEGMENT, obj);
475 return reinterpret_cast<jweak>(ref);
476}
477
478void JavaVMExt::DeleteGlobalRef(Thread* self, jobject obj) {
479 if (obj == nullptr) {
480 return;
481 }
482 WriterMutexLock mu(self, globals_lock_);
483 if (!globals_.Remove(IRT_FIRST_SEGMENT, obj)) {
484 LOG(WARNING) << "JNI WARNING: DeleteGlobalRef(" << obj << ") "
485 << "failed to find entry";
486 }
487}
488
489void JavaVMExt::DeleteWeakGlobalRef(Thread* self, jweak obj) {
490 if (obj == nullptr) {
491 return;
492 }
493 MutexLock mu(self, weak_globals_lock_);
494 if (!weak_globals_.Remove(IRT_FIRST_SEGMENT, obj)) {
495 LOG(WARNING) << "JNI WARNING: DeleteWeakGlobalRef(" << obj << ") "
496 << "failed to find entry";
497 }
498}
499
500static void ThreadEnableCheckJni(Thread* thread, void* arg) {
501 bool* check_jni = reinterpret_cast<bool*>(arg);
502 thread->GetJniEnv()->SetCheckJniEnabled(*check_jni);
503}
504
505bool JavaVMExt::SetCheckJniEnabled(bool enabled) {
506 bool old_check_jni = check_jni_;
507 check_jni_ = enabled;
508 functions = enabled ? GetCheckJniInvokeInterface() : unchecked_functions_;
509 MutexLock mu(Thread::Current(), *Locks::thread_list_lock_);
510 runtime_->GetThreadList()->ForEach(ThreadEnableCheckJni, &check_jni_);
511 return old_check_jni;
512}
513
514void JavaVMExt::DumpForSigQuit(std::ostream& os) {
515 os << "JNI: CheckJNI is " << (check_jni_ ? "on" : "off");
516 if (force_copy_) {
517 os << " (with forcecopy)";
518 }
519 Thread* self = Thread::Current();
520 {
Ian Rogers68d8b422014-07-17 11:09:10 -0700521 ReaderMutexLock mu(self, globals_lock_);
522 os << "; globals=" << globals_.Capacity();
523 }
524 {
525 MutexLock mu(self, weak_globals_lock_);
526 if (weak_globals_.Capacity() > 0) {
527 os << " (plus " << weak_globals_.Capacity() << " weak)";
528 }
529 }
530 os << '\n';
531
532 {
533 MutexLock mu(self, *Locks::jni_libraries_lock_);
534 os << "Libraries: " << Dumpable<Libraries>(*libraries_) << " (" << libraries_->size() << ")\n";
535 }
536}
537
538void JavaVMExt::DisallowNewWeakGlobals() {
539 MutexLock mu(Thread::Current(), weak_globals_lock_);
540 allow_new_weak_globals_ = false;
541}
542
543void JavaVMExt::AllowNewWeakGlobals() {
544 Thread* self = Thread::Current();
545 MutexLock mu(self, weak_globals_lock_);
546 allow_new_weak_globals_ = true;
547 weak_globals_add_condition_.Broadcast(self);
548}
549
550mirror::Object* JavaVMExt::DecodeGlobal(Thread* self, IndirectRef ref) {
551 return globals_.SynchronizedGet(self, &globals_lock_, ref);
552}
553
554mirror::Object* JavaVMExt::DecodeWeakGlobal(Thread* self, IndirectRef ref) {
555 MutexLock mu(self, weak_globals_lock_);
556 while (UNLIKELY(!allow_new_weak_globals_)) {
557 weak_globals_add_condition_.WaitHoldingLocks(self);
558 }
559 return weak_globals_.Get(ref);
560}
561
Ian Rogers68d8b422014-07-17 11:09:10 -0700562void JavaVMExt::DumpReferenceTables(std::ostream& os) {
563 Thread* self = Thread::Current();
564 {
565 ReaderMutexLock mu(self, globals_lock_);
566 globals_.Dump(os);
567 }
568 {
569 MutexLock mu(self, weak_globals_lock_);
570 weak_globals_.Dump(os);
571 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700572}
573
574bool JavaVMExt::LoadNativeLibrary(JNIEnv* env, const std::string& path, jobject class_loader,
575 std::string* error_msg) {
576 error_msg->clear();
577
578 // See if we've already loaded this library. If we have, and the class loader
579 // matches, return successfully without doing anything.
580 // TODO: for better results we should canonicalize the pathname (or even compare
581 // inodes). This implementation is fine if everybody is using System.loadLibrary.
582 SharedLibrary* library;
583 Thread* self = Thread::Current();
584 {
585 // TODO: move the locking (and more of this logic) into Libraries.
586 MutexLock mu(self, *Locks::jni_libraries_lock_);
587 library = libraries_->Get(path);
588 }
589 if (library != nullptr) {
590 if (env->IsSameObject(library->GetClassLoader(), class_loader) == JNI_FALSE) {
591 // The library will be associated with class_loader. The JNI
592 // spec says we can't load the same library into more than one
593 // class loader.
594 StringAppendF(error_msg, "Shared library \"%s\" already opened by "
595 "ClassLoader %p; can't open in ClassLoader %p",
596 path.c_str(), library->GetClassLoader(), class_loader);
597 LOG(WARNING) << error_msg;
598 return false;
599 }
600 VLOG(jni) << "[Shared library \"" << path << "\" already loaded in "
601 << " ClassLoader " << class_loader << "]";
602 if (!library->CheckOnLoadResult()) {
603 StringAppendF(error_msg, "JNI_OnLoad failed on a previous attempt "
604 "to load \"%s\"", path.c_str());
605 return false;
606 }
607 return true;
608 }
609
610 // Open the shared library. Because we're using a full path, the system
611 // doesn't have to search through LD_LIBRARY_PATH. (It may do so to
612 // resolve this library's dependencies though.)
613
614 // Failures here are expected when java.library.path has several entries
615 // and we have to hunt for the lib.
616
617 // Below we dlopen but there is no paired dlclose, this would be necessary if we supported
618 // class unloading. Libraries will only be unloaded when the reference count (incremented by
619 // dlopen) becomes zero from dlclose.
620
621 Locks::mutator_lock_->AssertNotHeld(self);
622 const char* path_str = path.empty() ? nullptr : path.c_str();
623 void* handle = dlopen(path_str, RTLD_LAZY);
624 bool needs_native_bridge = false;
625 if (handle == nullptr) {
Calin Juravlec8423522014-08-12 20:55:20 +0100626 if (android::NativeBridgeIsSupported(path_str)) {
627 handle = android::NativeBridgeLoadLibrary(path_str, RTLD_LAZY);
Ian Rogers68d8b422014-07-17 11:09:10 -0700628 needs_native_bridge = true;
629 }
630 }
631
632 VLOG(jni) << "[Call to dlopen(\"" << path << "\", RTLD_LAZY) returned " << handle << "]";
633
634 if (handle == nullptr) {
635 *error_msg = dlerror();
636 LOG(ERROR) << "dlopen(\"" << path << "\", RTLD_LAZY) failed: " << *error_msg;
637 return false;
638 }
639
640 if (env->ExceptionCheck() == JNI_TRUE) {
641 LOG(ERROR) << "Unexpected exception:";
642 env->ExceptionDescribe();
643 env->ExceptionClear();
644 }
645 // Create a new entry.
646 // TODO: move the locking (and more of this logic) into Libraries.
647 bool created_library = false;
648 {
649 // Create SharedLibrary ahead of taking the libraries lock to maintain lock ordering.
650 std::unique_ptr<SharedLibrary> new_library(
651 new SharedLibrary(env, self, path, handle, class_loader));
652 MutexLock mu(self, *Locks::jni_libraries_lock_);
653 library = libraries_->Get(path);
654 if (library == nullptr) { // We won race to get libraries_lock.
655 library = new_library.release();
656 libraries_->Put(path, library);
657 created_library = true;
658 }
659 }
660 if (!created_library) {
661 LOG(INFO) << "WOW: we lost a race to add shared library: "
662 << "\"" << path << "\" ClassLoader=" << class_loader;
663 return library->CheckOnLoadResult();
664 }
665 VLOG(jni) << "[Added shared library \"" << path << "\" for ClassLoader " << class_loader << "]";
666
667 bool was_successful = false;
668 void* sym;
669 if (needs_native_bridge) {
670 library->SetNeedsNativeBridge();
671 sym = library->FindSymbolWithNativeBridge("JNI_OnLoad", nullptr);
672 } else {
673 sym = dlsym(handle, "JNI_OnLoad");
674 }
675 if (sym == nullptr) {
676 VLOG(jni) << "[No JNI_OnLoad found in \"" << path << "\"]";
677 was_successful = true;
678 } else {
679 // Call JNI_OnLoad. We have to override the current class
680 // loader, which will always be "null" since the stuff at the
681 // top of the stack is around Runtime.loadLibrary(). (See
682 // the comments in the JNI FindClass function.)
683 ScopedLocalRef<jobject> old_class_loader(env, env->NewLocalRef(self->GetClassLoaderOverride()));
684 self->SetClassLoaderOverride(class_loader);
685
686 VLOG(jni) << "[Calling JNI_OnLoad in \"" << path << "\"]";
687 typedef int (*JNI_OnLoadFn)(JavaVM*, void*);
688 JNI_OnLoadFn jni_on_load = reinterpret_cast<JNI_OnLoadFn>(sym);
689 int version = (*jni_on_load)(this, nullptr);
690
691 self->SetClassLoaderOverride(old_class_loader.get());
692
693 if (version == JNI_ERR) {
694 StringAppendF(error_msg, "JNI_ERR returned from JNI_OnLoad in \"%s\"", path.c_str());
695 } else if (IsBadJniVersion(version)) {
696 StringAppendF(error_msg, "Bad JNI version returned from JNI_OnLoad in \"%s\": %d",
697 path.c_str(), version);
698 // It's unwise to call dlclose() here, but we can mark it
699 // as bad and ensure that future load attempts will fail.
700 // We don't know how far JNI_OnLoad got, so there could
701 // be some partially-initialized stuff accessible through
702 // newly-registered native method calls. We could try to
703 // unregister them, but that doesn't seem worthwhile.
704 } else {
705 was_successful = true;
706 }
707 VLOG(jni) << "[Returned " << (was_successful ? "successfully" : "failure")
708 << " from JNI_OnLoad in \"" << path << "\"]";
709 }
710
711 library->SetResult(was_successful);
712 return was_successful;
713}
714
715void* JavaVMExt::FindCodeForNativeMethod(mirror::ArtMethod* m) {
716 CHECK(m->IsNative());
717 mirror::Class* c = m->GetDeclaringClass();
718 // If this is a static method, it could be called before the class has been initialized.
719 CHECK(c->IsInitializing()) << c->GetStatus() << " " << PrettyMethod(m);
720 std::string detail;
721 void* native_method;
722 Thread* self = Thread::Current();
723 {
724 MutexLock mu(self, *Locks::jni_libraries_lock_);
725 native_method = libraries_->FindNativeMethod(m, detail);
726 }
727 // Throwing can cause libraries_lock to be reacquired.
728 if (native_method == nullptr) {
729 ThrowLocation throw_location = self->GetCurrentLocationForThrow();
730 self->ThrowNewException(throw_location, "Ljava/lang/UnsatisfiedLinkError;", detail.c_str());
731 }
732 return native_method;
733}
734
735void JavaVMExt::SweepJniWeakGlobals(IsMarkedCallback* callback, void* arg) {
736 MutexLock mu(Thread::Current(), weak_globals_lock_);
737 for (mirror::Object** entry : weak_globals_) {
738 // Since this is called by the GC, we don't need a read barrier.
739 mirror::Object* obj = *entry;
Hiroshi Yamauchi8a741172014-09-08 13:22:56 -0700740 if (obj == nullptr) {
741 // Need to skip null here to distinguish between null entries
742 // and cleared weak ref entries.
743 continue;
744 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700745 mirror::Object* new_obj = callback(obj, arg);
746 if (new_obj == nullptr) {
Ian Rogersc0542af2014-09-03 16:16:56 -0700747 new_obj = Runtime::Current()->GetClearedJniWeakGlobal();
Ian Rogers68d8b422014-07-17 11:09:10 -0700748 }
749 *entry = new_obj;
750 }
751}
752
753void JavaVMExt::VisitRoots(RootCallback* callback, void* arg) {
754 Thread* self = Thread::Current();
755 {
756 ReaderMutexLock mu(self, globals_lock_);
757 globals_.VisitRoots(callback, arg, 0, kRootJNIGlobal);
758 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700759 // The weak_globals table is visited by the GC itself (because it mutates the table).
760}
761
762// JNI Invocation interface.
763
764extern "C" jint JNI_CreateJavaVM(JavaVM** p_vm, JNIEnv** p_env, void* vm_args) {
765 const JavaVMInitArgs* args = static_cast<JavaVMInitArgs*>(vm_args);
766 if (IsBadJniVersion(args->version)) {
767 LOG(ERROR) << "Bad JNI version passed to CreateJavaVM: " << args->version;
768 return JNI_EVERSION;
769 }
770 RuntimeOptions options;
771 for (int i = 0; i < args->nOptions; ++i) {
772 JavaVMOption* option = &args->options[i];
773 options.push_back(std::make_pair(std::string(option->optionString), option->extraInfo));
774 }
775 bool ignore_unrecognized = args->ignoreUnrecognized;
776 if (!Runtime::Create(options, ignore_unrecognized)) {
777 return JNI_ERR;
778 }
779 Runtime* runtime = Runtime::Current();
780 bool started = runtime->Start();
781 if (!started) {
782 delete Thread::Current()->GetJniEnv();
783 delete runtime->GetJavaVM();
784 LOG(WARNING) << "CreateJavaVM failed";
785 return JNI_ERR;
786 }
787 *p_env = Thread::Current()->GetJniEnv();
788 *p_vm = runtime->GetJavaVM();
789 return JNI_OK;
790}
791
792extern "C" jint JNI_GetCreatedJavaVMs(JavaVM** vms, jsize, jsize* vm_count) {
793 Runtime* runtime = Runtime::Current();
794 if (runtime == nullptr) {
795 *vm_count = 0;
796 } else {
797 *vm_count = 1;
798 vms[0] = runtime->GetJavaVM();
799 }
800 return JNI_OK;
801}
802
803// Historically unsupported.
804extern "C" jint JNI_GetDefaultJavaVMInitArgs(void* /*vm_args*/) {
805 return JNI_ERR;
806}
807
808} // namespace art