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