xref: /aosp_15_r20/art/runtime/jni/java_vm_ext.cc (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
1*795d594fSAndroid Build Coastguard Worker /*
2*795d594fSAndroid Build Coastguard Worker  * Copyright (C) 2011 The Android Open Source Project
3*795d594fSAndroid Build Coastguard Worker  *
4*795d594fSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*795d594fSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*795d594fSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*795d594fSAndroid Build Coastguard Worker  *
8*795d594fSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*795d594fSAndroid Build Coastguard Worker  *
10*795d594fSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*795d594fSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*795d594fSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*795d594fSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*795d594fSAndroid Build Coastguard Worker  * limitations under the License.
15*795d594fSAndroid Build Coastguard Worker  */
16*795d594fSAndroid Build Coastguard Worker 
17*795d594fSAndroid Build Coastguard Worker #include "java_vm_ext-inl.h"
18*795d594fSAndroid Build Coastguard Worker 
19*795d594fSAndroid Build Coastguard Worker #include <dlfcn.h>
20*795d594fSAndroid Build Coastguard Worker #include <string_view>
21*795d594fSAndroid Build Coastguard Worker 
22*795d594fSAndroid Build Coastguard Worker #include "android-base/stringprintf.h"
23*795d594fSAndroid Build Coastguard Worker 
24*795d594fSAndroid Build Coastguard Worker #include "art_method-inl.h"
25*795d594fSAndroid Build Coastguard Worker #include "base/dumpable.h"
26*795d594fSAndroid Build Coastguard Worker #include "base/mutex-inl.h"
27*795d594fSAndroid Build Coastguard Worker #include "base/sdk_version.h"
28*795d594fSAndroid Build Coastguard Worker #include "base/stl_util.h"
29*795d594fSAndroid Build Coastguard Worker #include "base/systrace.h"
30*795d594fSAndroid Build Coastguard Worker #include "check_jni.h"
31*795d594fSAndroid Build Coastguard Worker #include "dex/dex_file-inl.h"
32*795d594fSAndroid Build Coastguard Worker #include "entrypoints/entrypoint_utils-inl.h"
33*795d594fSAndroid Build Coastguard Worker #include "fault_handler.h"
34*795d594fSAndroid Build Coastguard Worker #include "gc/allocation_record.h"
35*795d594fSAndroid Build Coastguard Worker #include "gc/heap.h"
36*795d594fSAndroid Build Coastguard Worker #include "gc_root-inl.h"
37*795d594fSAndroid Build Coastguard Worker #include "indirect_reference_table-inl.h"
38*795d594fSAndroid Build Coastguard Worker #include "jni_internal.h"
39*795d594fSAndroid Build Coastguard Worker #include "mirror/class-inl.h"
40*795d594fSAndroid Build Coastguard Worker #include "mirror/class_loader.h"
41*795d594fSAndroid Build Coastguard Worker #include "mirror/dex_cache-inl.h"
42*795d594fSAndroid Build Coastguard Worker #include "nativebridge/native_bridge.h"
43*795d594fSAndroid Build Coastguard Worker #include "nativehelper/scoped_local_ref.h"
44*795d594fSAndroid Build Coastguard Worker #include "nativehelper/scoped_utf_chars.h"
45*795d594fSAndroid Build Coastguard Worker #include "nativeloader/native_loader.h"
46*795d594fSAndroid Build Coastguard Worker #include "parsed_options.h"
47*795d594fSAndroid Build Coastguard Worker #include "runtime-inl.h"
48*795d594fSAndroid Build Coastguard Worker #include "runtime_options.h"
49*795d594fSAndroid Build Coastguard Worker #include "scoped_thread_state_change-inl.h"
50*795d594fSAndroid Build Coastguard Worker #include "sigchain.h"
51*795d594fSAndroid Build Coastguard Worker #include "thread-inl.h"
52*795d594fSAndroid Build Coastguard Worker #include "thread_list.h"
53*795d594fSAndroid Build Coastguard Worker #include "ti/agent.h"
54*795d594fSAndroid Build Coastguard Worker #include "well_known_classes-inl.h"
55*795d594fSAndroid Build Coastguard Worker 
56*795d594fSAndroid Build Coastguard Worker namespace art HIDDEN {
57*795d594fSAndroid Build Coastguard Worker 
58*795d594fSAndroid Build Coastguard Worker using android::base::StringAppendF;
59*795d594fSAndroid Build Coastguard Worker using android::base::StringAppendV;
60*795d594fSAndroid Build Coastguard Worker 
61*795d594fSAndroid Build Coastguard Worker // Maximum number of global references (must fit in 16 bits).
62*795d594fSAndroid Build Coastguard Worker static constexpr size_t kGlobalsMax = 51200;
63*795d594fSAndroid Build Coastguard Worker 
64*795d594fSAndroid Build Coastguard Worker // Maximum number of weak global references (must fit in 16 bits).
65*795d594fSAndroid Build Coastguard Worker static constexpr size_t kWeakGlobalsMax = 51200;
66*795d594fSAndroid Build Coastguard Worker 
IsBadJniVersion(int version)67*795d594fSAndroid Build Coastguard Worker bool JavaVMExt::IsBadJniVersion(int version) {
68*795d594fSAndroid Build Coastguard Worker   // We don't support JNI_VERSION_1_1. These are the only other valid versions.
69*795d594fSAndroid Build Coastguard Worker   return version != JNI_VERSION_1_2 && version != JNI_VERSION_1_4 && version != JNI_VERSION_1_6;
70*795d594fSAndroid Build Coastguard Worker }
71*795d594fSAndroid Build Coastguard Worker 
72*795d594fSAndroid Build Coastguard Worker class SharedLibrary {
73*795d594fSAndroid Build Coastguard Worker  public:
SharedLibrary(JNIEnv * env,Thread * self,const std::string & path,void * handle,bool needs_native_bridge,jobject class_loader,void * class_loader_allocator)74*795d594fSAndroid Build Coastguard Worker   SharedLibrary(JNIEnv* env, Thread* self, const std::string& path, void* handle,
75*795d594fSAndroid Build Coastguard Worker                 bool needs_native_bridge, jobject class_loader, void* class_loader_allocator)
76*795d594fSAndroid Build Coastguard Worker       : path_(path),
77*795d594fSAndroid Build Coastguard Worker         handle_(handle),
78*795d594fSAndroid Build Coastguard Worker         needs_native_bridge_(needs_native_bridge),
79*795d594fSAndroid Build Coastguard Worker         class_loader_(env->NewWeakGlobalRef(class_loader)),
80*795d594fSAndroid Build Coastguard Worker         class_loader_allocator_(class_loader_allocator),
81*795d594fSAndroid Build Coastguard Worker         jni_on_load_lock_("JNI_OnLoad lock"),
82*795d594fSAndroid Build Coastguard Worker         jni_on_load_cond_("JNI_OnLoad condition variable", jni_on_load_lock_),
83*795d594fSAndroid Build Coastguard Worker         jni_on_load_thread_id_(self->GetThreadId()),
84*795d594fSAndroid Build Coastguard Worker         jni_on_load_result_(kPending) {
85*795d594fSAndroid Build Coastguard Worker     CHECK(class_loader_allocator_ != nullptr);
86*795d594fSAndroid Build Coastguard Worker   }
87*795d594fSAndroid Build Coastguard Worker 
~SharedLibrary()88*795d594fSAndroid Build Coastguard Worker   ~SharedLibrary() {
89*795d594fSAndroid Build Coastguard Worker     Thread* self = Thread::Current();
90*795d594fSAndroid Build Coastguard Worker     if (self != nullptr) {
91*795d594fSAndroid Build Coastguard Worker       self->GetJniEnv()->DeleteWeakGlobalRef(class_loader_);
92*795d594fSAndroid Build Coastguard Worker     }
93*795d594fSAndroid Build Coastguard Worker 
94*795d594fSAndroid Build Coastguard Worker     char* error_msg = nullptr;
95*795d594fSAndroid Build Coastguard Worker     if (!android::CloseNativeLibrary(handle_, needs_native_bridge_, &error_msg)) {
96*795d594fSAndroid Build Coastguard Worker       LOG(WARNING) << "Error while unloading native library \"" << path_ << "\": " << error_msg;
97*795d594fSAndroid Build Coastguard Worker       android::NativeLoaderFreeErrorMessage(error_msg);
98*795d594fSAndroid Build Coastguard Worker     }
99*795d594fSAndroid Build Coastguard Worker   }
100*795d594fSAndroid Build Coastguard Worker 
GetClassLoader() const101*795d594fSAndroid Build Coastguard Worker   jweak GetClassLoader() const {
102*795d594fSAndroid Build Coastguard Worker     return class_loader_;
103*795d594fSAndroid Build Coastguard Worker   }
104*795d594fSAndroid Build Coastguard Worker 
GetClassLoaderAllocator() const105*795d594fSAndroid Build Coastguard Worker   const void* GetClassLoaderAllocator() const {
106*795d594fSAndroid Build Coastguard Worker     return class_loader_allocator_;
107*795d594fSAndroid Build Coastguard Worker   }
108*795d594fSAndroid Build Coastguard Worker 
GetPath() const109*795d594fSAndroid Build Coastguard Worker   const std::string& GetPath() const {
110*795d594fSAndroid Build Coastguard Worker     return path_;
111*795d594fSAndroid Build Coastguard Worker   }
112*795d594fSAndroid Build Coastguard Worker 
113*795d594fSAndroid Build Coastguard Worker   /*
114*795d594fSAndroid Build Coastguard Worker    * Check the result of an earlier call to JNI_OnLoad on this library.
115*795d594fSAndroid Build Coastguard Worker    * If the call has not yet finished in another thread, wait for it.
116*795d594fSAndroid Build Coastguard Worker    */
CheckOnLoadResult()117*795d594fSAndroid Build Coastguard Worker   bool CheckOnLoadResult()
118*795d594fSAndroid Build Coastguard Worker       REQUIRES(!jni_on_load_lock_) {
119*795d594fSAndroid Build Coastguard Worker     Thread* self = Thread::Current();
120*795d594fSAndroid Build Coastguard Worker     bool okay;
121*795d594fSAndroid Build Coastguard Worker     {
122*795d594fSAndroid Build Coastguard Worker       MutexLock mu(self, jni_on_load_lock_);
123*795d594fSAndroid Build Coastguard Worker 
124*795d594fSAndroid Build Coastguard Worker       if (jni_on_load_thread_id_ == self->GetThreadId()) {
125*795d594fSAndroid Build Coastguard Worker         // Check this so we don't end up waiting for ourselves.  We need to return "true" so the
126*795d594fSAndroid Build Coastguard Worker         // caller can continue.
127*795d594fSAndroid Build Coastguard Worker         LOG(INFO) << *self << " recursive attempt to load library " << "\"" << path_ << "\"";
128*795d594fSAndroid Build Coastguard Worker         okay = true;
129*795d594fSAndroid Build Coastguard Worker       } else {
130*795d594fSAndroid Build Coastguard Worker         while (jni_on_load_result_ == kPending) {
131*795d594fSAndroid Build Coastguard Worker           VLOG(jni) << "[" << *self << " waiting for \"" << path_ << "\" " << "JNI_OnLoad...]";
132*795d594fSAndroid Build Coastguard Worker           jni_on_load_cond_.Wait(self);
133*795d594fSAndroid Build Coastguard Worker         }
134*795d594fSAndroid Build Coastguard Worker 
135*795d594fSAndroid Build Coastguard Worker         okay = (jni_on_load_result_ == kOkay);
136*795d594fSAndroid Build Coastguard Worker         VLOG(jni) << "[Earlier JNI_OnLoad for \"" << path_ << "\" "
137*795d594fSAndroid Build Coastguard Worker             << (okay ? "succeeded" : "failed") << "]";
138*795d594fSAndroid Build Coastguard Worker       }
139*795d594fSAndroid Build Coastguard Worker     }
140*795d594fSAndroid Build Coastguard Worker     return okay;
141*795d594fSAndroid Build Coastguard Worker   }
142*795d594fSAndroid Build Coastguard Worker 
SetResult(bool result)143*795d594fSAndroid Build Coastguard Worker   void SetResult(bool result) REQUIRES(!jni_on_load_lock_) {
144*795d594fSAndroid Build Coastguard Worker     Thread* self = Thread::Current();
145*795d594fSAndroid Build Coastguard Worker     MutexLock mu(self, jni_on_load_lock_);
146*795d594fSAndroid Build Coastguard Worker 
147*795d594fSAndroid Build Coastguard Worker     jni_on_load_result_ = result ? kOkay : kFailed;
148*795d594fSAndroid Build Coastguard Worker     jni_on_load_thread_id_ = 0;
149*795d594fSAndroid Build Coastguard Worker 
150*795d594fSAndroid Build Coastguard Worker     // Broadcast a wakeup to anybody sleeping on the condition variable.
151*795d594fSAndroid Build Coastguard Worker     jni_on_load_cond_.Broadcast(self);
152*795d594fSAndroid Build Coastguard Worker   }
153*795d594fSAndroid Build Coastguard Worker 
SetNeedsNativeBridge(bool needs)154*795d594fSAndroid Build Coastguard Worker   void SetNeedsNativeBridge(bool needs) {
155*795d594fSAndroid Build Coastguard Worker     needs_native_bridge_ = needs;
156*795d594fSAndroid Build Coastguard Worker   }
157*795d594fSAndroid Build Coastguard Worker 
NeedsNativeBridge() const158*795d594fSAndroid Build Coastguard Worker   bool NeedsNativeBridge() const {
159*795d594fSAndroid Build Coastguard Worker     return needs_native_bridge_;
160*795d594fSAndroid Build Coastguard Worker   }
161*795d594fSAndroid Build Coastguard Worker 
162*795d594fSAndroid Build Coastguard Worker   // No mutator lock since dlsym may block for a while if another thread is doing dlopen.
FindSymbol(const std::string & symbol_name,const char * shorty,android::JNICallType jni_call_type)163*795d594fSAndroid Build Coastguard Worker   void* FindSymbol(const std::string& symbol_name,
164*795d594fSAndroid Build Coastguard Worker                    const char* shorty,
165*795d594fSAndroid Build Coastguard Worker                    android::JNICallType jni_call_type) REQUIRES(!Locks::mutator_lock_) {
166*795d594fSAndroid Build Coastguard Worker     return NeedsNativeBridge() ? FindSymbolWithNativeBridge(symbol_name, shorty, jni_call_type) :
167*795d594fSAndroid Build Coastguard Worker                                  FindSymbolWithoutNativeBridge(symbol_name);
168*795d594fSAndroid Build Coastguard Worker   }
169*795d594fSAndroid Build Coastguard Worker 
170*795d594fSAndroid Build Coastguard Worker   // No mutator lock since dlsym may block for a while if another thread is doing dlopen.
FindSymbolWithoutNativeBridge(const std::string & symbol_name)171*795d594fSAndroid Build Coastguard Worker   void* FindSymbolWithoutNativeBridge(const std::string& symbol_name)
172*795d594fSAndroid Build Coastguard Worker       REQUIRES(!Locks::mutator_lock_) {
173*795d594fSAndroid Build Coastguard Worker     CHECK(!NeedsNativeBridge());
174*795d594fSAndroid Build Coastguard Worker 
175*795d594fSAndroid Build Coastguard Worker     return dlsym(handle_, symbol_name.c_str());
176*795d594fSAndroid Build Coastguard Worker   }
177*795d594fSAndroid Build Coastguard Worker 
FindSymbolWithNativeBridge(const std::string & symbol_name,const char * shorty,android::JNICallType jni_call_type)178*795d594fSAndroid Build Coastguard Worker   void* FindSymbolWithNativeBridge(const std::string& symbol_name,
179*795d594fSAndroid Build Coastguard Worker                                    const char* shorty,
180*795d594fSAndroid Build Coastguard Worker                                    android::JNICallType jni_call_type)
181*795d594fSAndroid Build Coastguard Worker       REQUIRES(!Locks::mutator_lock_) {
182*795d594fSAndroid Build Coastguard Worker     CHECK(NeedsNativeBridge());
183*795d594fSAndroid Build Coastguard Worker 
184*795d594fSAndroid Build Coastguard Worker     uint32_t len = 0;
185*795d594fSAndroid Build Coastguard Worker     return android::NativeBridgeGetTrampoline2(
186*795d594fSAndroid Build Coastguard Worker         handle_, symbol_name.c_str(), shorty, len, jni_call_type);
187*795d594fSAndroid Build Coastguard Worker   }
188*795d594fSAndroid Build Coastguard Worker 
189*795d594fSAndroid Build Coastguard Worker  private:
190*795d594fSAndroid Build Coastguard Worker   enum JNI_OnLoadState {
191*795d594fSAndroid Build Coastguard Worker     kPending,
192*795d594fSAndroid Build Coastguard Worker     kFailed,
193*795d594fSAndroid Build Coastguard Worker     kOkay,
194*795d594fSAndroid Build Coastguard Worker   };
195*795d594fSAndroid Build Coastguard Worker 
196*795d594fSAndroid Build Coastguard Worker   // Path to library "/system/lib/libjni.so".
197*795d594fSAndroid Build Coastguard Worker   const std::string path_;
198*795d594fSAndroid Build Coastguard Worker 
199*795d594fSAndroid Build Coastguard Worker   // The void* returned by dlopen(3).
200*795d594fSAndroid Build Coastguard Worker   void* const handle_;
201*795d594fSAndroid Build Coastguard Worker 
202*795d594fSAndroid Build Coastguard Worker   // True if a native bridge is required.
203*795d594fSAndroid Build Coastguard Worker   bool needs_native_bridge_;
204*795d594fSAndroid Build Coastguard Worker 
205*795d594fSAndroid Build Coastguard Worker   // The ClassLoader this library is associated with, a weak global JNI reference that is
206*795d594fSAndroid Build Coastguard Worker   // created/deleted with the scope of the library.
207*795d594fSAndroid Build Coastguard Worker   const jweak class_loader_;
208*795d594fSAndroid Build Coastguard Worker   // Used to do equality check on class loaders so we can avoid decoding the weak root and read
209*795d594fSAndroid Build Coastguard Worker   // barriers that mess with class unloading.
210*795d594fSAndroid Build Coastguard Worker   const void* class_loader_allocator_;
211*795d594fSAndroid Build Coastguard Worker 
212*795d594fSAndroid Build Coastguard Worker   // Guards remaining items.
213*795d594fSAndroid Build Coastguard Worker   Mutex jni_on_load_lock_ DEFAULT_MUTEX_ACQUIRED_AFTER;
214*795d594fSAndroid Build Coastguard Worker   // Wait for JNI_OnLoad in other thread.
215*795d594fSAndroid Build Coastguard Worker   ConditionVariable jni_on_load_cond_ GUARDED_BY(jni_on_load_lock_);
216*795d594fSAndroid Build Coastguard Worker   // Recursive invocation guard.
217*795d594fSAndroid Build Coastguard Worker   uint32_t jni_on_load_thread_id_ GUARDED_BY(jni_on_load_lock_);
218*795d594fSAndroid Build Coastguard Worker   // Result of earlier JNI_OnLoad call.
219*795d594fSAndroid Build Coastguard Worker   JNI_OnLoadState jni_on_load_result_ GUARDED_BY(jni_on_load_lock_);
220*795d594fSAndroid Build Coastguard Worker };
221*795d594fSAndroid Build Coastguard Worker 
222*795d594fSAndroid Build Coastguard Worker // This exists mainly to keep implementation details out of the header file.
223*795d594fSAndroid Build Coastguard Worker class Libraries {
224*795d594fSAndroid Build Coastguard Worker  public:
Libraries()225*795d594fSAndroid Build Coastguard Worker   Libraries() {
226*795d594fSAndroid Build Coastguard Worker   }
227*795d594fSAndroid Build Coastguard Worker 
~Libraries()228*795d594fSAndroid Build Coastguard Worker   ~Libraries() {
229*795d594fSAndroid Build Coastguard Worker     STLDeleteValues(&libraries_);
230*795d594fSAndroid Build Coastguard Worker   }
231*795d594fSAndroid Build Coastguard Worker 
232*795d594fSAndroid Build Coastguard Worker   // NO_THREAD_SAFETY_ANALYSIS as this is during runtime shutdown, and we have
233*795d594fSAndroid Build Coastguard Worker   // no thread to lock this with.
UnloadBootNativeLibraries(JavaVM * vm) const234*795d594fSAndroid Build Coastguard Worker   void UnloadBootNativeLibraries(JavaVM* vm) const NO_THREAD_SAFETY_ANALYSIS {
235*795d594fSAndroid Build Coastguard Worker     CHECK(Thread::Current() == nullptr);
236*795d594fSAndroid Build Coastguard Worker     std::vector<SharedLibrary*> unload_libraries;
237*795d594fSAndroid Build Coastguard Worker     for (auto it = libraries_.begin(); it != libraries_.end(); ++it) {
238*795d594fSAndroid Build Coastguard Worker       SharedLibrary* const library = it->second;
239*795d594fSAndroid Build Coastguard Worker       if (library->GetClassLoader() == nullptr) {
240*795d594fSAndroid Build Coastguard Worker         unload_libraries.push_back(library);
241*795d594fSAndroid Build Coastguard Worker       }
242*795d594fSAndroid Build Coastguard Worker     }
243*795d594fSAndroid Build Coastguard Worker     UnloadLibraries(vm, unload_libraries);
244*795d594fSAndroid Build Coastguard Worker   }
245*795d594fSAndroid Build Coastguard Worker 
246*795d594fSAndroid Build Coastguard Worker   // NO_THREAD_SAFETY_ANALYSIS since this may be called from Dumpable. Dumpable can't be annotated
247*795d594fSAndroid Build Coastguard Worker   // properly due to the template. The caller should be holding the jni_libraries_lock_.
Dump(std::ostream & os) const248*795d594fSAndroid Build Coastguard Worker   void Dump(std::ostream& os) const NO_THREAD_SAFETY_ANALYSIS {
249*795d594fSAndroid Build Coastguard Worker     Locks::jni_libraries_lock_->AssertHeld(Thread::Current());
250*795d594fSAndroid Build Coastguard Worker     bool first = true;
251*795d594fSAndroid Build Coastguard Worker     for (const auto& library : libraries_) {
252*795d594fSAndroid Build Coastguard Worker       if (!first) {
253*795d594fSAndroid Build Coastguard Worker         os << ' ';
254*795d594fSAndroid Build Coastguard Worker       }
255*795d594fSAndroid Build Coastguard Worker       first = false;
256*795d594fSAndroid Build Coastguard Worker       os << library.first;
257*795d594fSAndroid Build Coastguard Worker     }
258*795d594fSAndroid Build Coastguard Worker   }
259*795d594fSAndroid Build Coastguard Worker 
size() const260*795d594fSAndroid Build Coastguard Worker   size_t size() const REQUIRES(Locks::jni_libraries_lock_) {
261*795d594fSAndroid Build Coastguard Worker     return libraries_.size();
262*795d594fSAndroid Build Coastguard Worker   }
263*795d594fSAndroid Build Coastguard Worker 
Get(const std::string & path)264*795d594fSAndroid Build Coastguard Worker   SharedLibrary* Get(const std::string& path) REQUIRES(Locks::jni_libraries_lock_) {
265*795d594fSAndroid Build Coastguard Worker     auto it = libraries_.find(path);
266*795d594fSAndroid Build Coastguard Worker     return (it == libraries_.end()) ? nullptr : it->second;
267*795d594fSAndroid Build Coastguard Worker   }
268*795d594fSAndroid Build Coastguard Worker 
Put(const std::string & path,SharedLibrary * library)269*795d594fSAndroid Build Coastguard Worker   void Put(const std::string& path, SharedLibrary* library)
270*795d594fSAndroid Build Coastguard Worker       REQUIRES(Locks::jni_libraries_lock_) {
271*795d594fSAndroid Build Coastguard Worker     libraries_.Put(path, library);
272*795d594fSAndroid Build Coastguard Worker   }
273*795d594fSAndroid Build Coastguard Worker 
274*795d594fSAndroid Build Coastguard Worker   // See section 11.3 "Linking Native Methods" of the JNI spec.
FindNativeMethod(Thread * self,ArtMethod * m,std::string * detail,bool can_suspend)275*795d594fSAndroid Build Coastguard Worker   void* FindNativeMethod(Thread* self, ArtMethod* m, std::string* detail, bool can_suspend)
276*795d594fSAndroid Build Coastguard Worker       REQUIRES(!Locks::jni_libraries_lock_)
277*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_) {
278*795d594fSAndroid Build Coastguard Worker     std::string jni_short_name(m->JniShortName());
279*795d594fSAndroid Build Coastguard Worker     std::string jni_long_name(m->JniLongName());
280*795d594fSAndroid Build Coastguard Worker     const ObjPtr<mirror::ClassLoader> declaring_class_loader =
281*795d594fSAndroid Build Coastguard Worker         m->GetDeclaringClass()->GetClassLoader();
282*795d594fSAndroid Build Coastguard Worker     void* const declaring_class_loader_allocator =
283*795d594fSAndroid Build Coastguard Worker         Runtime::Current()->GetClassLinker()->GetAllocatorForClassLoader(declaring_class_loader);
284*795d594fSAndroid Build Coastguard Worker     CHECK(declaring_class_loader_allocator != nullptr);
285*795d594fSAndroid Build Coastguard Worker     // TODO: Avoid calling GetShorty here to prevent dirtying dex pages?
286*795d594fSAndroid Build Coastguard Worker     const char* shorty = m->GetShorty();
287*795d594fSAndroid Build Coastguard Worker     void* native_code = nullptr;
288*795d594fSAndroid Build Coastguard Worker     android::JNICallType jni_call_type =
289*795d594fSAndroid Build Coastguard Worker         m->IsCriticalNative() ? android::kJNICallTypeCriticalNative : android::kJNICallTypeRegular;
290*795d594fSAndroid Build Coastguard Worker     if (can_suspend) {
291*795d594fSAndroid Build Coastguard Worker       // Go to suspended since dlsym may block for a long time if other threads are using dlopen.
292*795d594fSAndroid Build Coastguard Worker       ScopedThreadSuspension sts(self, ThreadState::kNative);
293*795d594fSAndroid Build Coastguard Worker       native_code = FindNativeMethodInternal(self,
294*795d594fSAndroid Build Coastguard Worker                                              declaring_class_loader_allocator,
295*795d594fSAndroid Build Coastguard Worker                                              shorty,
296*795d594fSAndroid Build Coastguard Worker                                              jni_short_name,
297*795d594fSAndroid Build Coastguard Worker                                              jni_long_name,
298*795d594fSAndroid Build Coastguard Worker                                              jni_call_type);
299*795d594fSAndroid Build Coastguard Worker     } else {
300*795d594fSAndroid Build Coastguard Worker       native_code = FindNativeMethodInternal(self,
301*795d594fSAndroid Build Coastguard Worker                                              declaring_class_loader_allocator,
302*795d594fSAndroid Build Coastguard Worker                                              shorty,
303*795d594fSAndroid Build Coastguard Worker                                              jni_short_name,
304*795d594fSAndroid Build Coastguard Worker                                              jni_long_name,
305*795d594fSAndroid Build Coastguard Worker                                              jni_call_type);
306*795d594fSAndroid Build Coastguard Worker     }
307*795d594fSAndroid Build Coastguard Worker     if (native_code != nullptr) {
308*795d594fSAndroid Build Coastguard Worker       return native_code;
309*795d594fSAndroid Build Coastguard Worker     }
310*795d594fSAndroid Build Coastguard Worker     if (detail != nullptr) {
311*795d594fSAndroid Build Coastguard Worker       *detail += "No implementation found for ";
312*795d594fSAndroid Build Coastguard Worker       *detail += m->PrettyMethod();
313*795d594fSAndroid Build Coastguard Worker       *detail += " (tried " + jni_short_name + " and " + jni_long_name + ")";
314*795d594fSAndroid Build Coastguard Worker       *detail += " - is the library loaded, e.g. System.loadLibrary?";
315*795d594fSAndroid Build Coastguard Worker     }
316*795d594fSAndroid Build Coastguard Worker     return nullptr;
317*795d594fSAndroid Build Coastguard Worker   }
318*795d594fSAndroid Build Coastguard Worker 
FindNativeMethodInternal(Thread * self,void * declaring_class_loader_allocator,const char * shorty,const std::string & jni_short_name,const std::string & jni_long_name,android::JNICallType jni_call_type)319*795d594fSAndroid Build Coastguard Worker   void* FindNativeMethodInternal(Thread* self,
320*795d594fSAndroid Build Coastguard Worker                                  void* declaring_class_loader_allocator,
321*795d594fSAndroid Build Coastguard Worker                                  const char* shorty,
322*795d594fSAndroid Build Coastguard Worker                                  const std::string& jni_short_name,
323*795d594fSAndroid Build Coastguard Worker                                  const std::string& jni_long_name,
324*795d594fSAndroid Build Coastguard Worker                                  android::JNICallType jni_call_type)
325*795d594fSAndroid Build Coastguard Worker       REQUIRES(!Locks::jni_libraries_lock_) {
326*795d594fSAndroid Build Coastguard Worker     MutexLock mu(self, *Locks::jni_libraries_lock_);
327*795d594fSAndroid Build Coastguard Worker     for (const auto& lib : libraries_) {
328*795d594fSAndroid Build Coastguard Worker       SharedLibrary* const library = lib.second;
329*795d594fSAndroid Build Coastguard Worker       // Use the allocator address for class loader equality to avoid unnecessary weak root decode.
330*795d594fSAndroid Build Coastguard Worker       if (library->GetClassLoaderAllocator() != declaring_class_loader_allocator) {
331*795d594fSAndroid Build Coastguard Worker         // We only search libraries loaded by the appropriate ClassLoader.
332*795d594fSAndroid Build Coastguard Worker         continue;
333*795d594fSAndroid Build Coastguard Worker       }
334*795d594fSAndroid Build Coastguard Worker       // Try the short name then the long name...
335*795d594fSAndroid Build Coastguard Worker       const char* arg_shorty = library->NeedsNativeBridge() ? shorty : nullptr;
336*795d594fSAndroid Build Coastguard Worker       void* fn = library->FindSymbol(jni_short_name, arg_shorty, jni_call_type);
337*795d594fSAndroid Build Coastguard Worker       if (fn == nullptr) {
338*795d594fSAndroid Build Coastguard Worker         fn = library->FindSymbol(jni_long_name, arg_shorty, jni_call_type);
339*795d594fSAndroid Build Coastguard Worker       }
340*795d594fSAndroid Build Coastguard Worker       if (fn != nullptr) {
341*795d594fSAndroid Build Coastguard Worker         VLOG(jni) << "[Found native code for " << jni_long_name
342*795d594fSAndroid Build Coastguard Worker                   << " in \"" << library->GetPath() << "\"]";
343*795d594fSAndroid Build Coastguard Worker         return fn;
344*795d594fSAndroid Build Coastguard Worker       }
345*795d594fSAndroid Build Coastguard Worker     }
346*795d594fSAndroid Build Coastguard Worker     return nullptr;
347*795d594fSAndroid Build Coastguard Worker   }
348*795d594fSAndroid Build Coastguard Worker 
349*795d594fSAndroid Build Coastguard Worker   // Unload native libraries with cleared class loaders.
UnloadNativeLibraries()350*795d594fSAndroid Build Coastguard Worker   void UnloadNativeLibraries()
351*795d594fSAndroid Build Coastguard Worker       REQUIRES(!Locks::jni_libraries_lock_)
352*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_) {
353*795d594fSAndroid Build Coastguard Worker     Thread* const self = Thread::Current();
354*795d594fSAndroid Build Coastguard Worker     std::vector<SharedLibrary*> unload_libraries;
355*795d594fSAndroid Build Coastguard Worker     {
356*795d594fSAndroid Build Coastguard Worker       // jni_libraries_lock_ appears to be held long enough that we just retry once, rather than
357*795d594fSAndroid Build Coastguard Worker       // spinning.
358*795d594fSAndroid Build Coastguard Worker       int retries = 0;
359*795d594fSAndroid Build Coastguard Worker       static constexpr int MAX_RETRIES = 5;
360*795d594fSAndroid Build Coastguard Worker       while (!Locks::jni_libraries_lock_->ExclusiveTryLock(self)) {
361*795d594fSAndroid Build Coastguard Worker         if (Runtime::Current()->IsZygote()) {
362*795d594fSAndroid Build Coastguard Worker           // Do not risk deferring to the child processes.
363*795d594fSAndroid Build Coastguard Worker           Locks::jni_libraries_lock_->ExclusiveLock(self);
364*795d594fSAndroid Build Coastguard Worker           break;
365*795d594fSAndroid Build Coastguard Worker         }
366*795d594fSAndroid Build Coastguard Worker         if (++retries > MAX_RETRIES) {
367*795d594fSAndroid Build Coastguard Worker           // We do not want to block indefinitely here, for fear of timeouts. See b/374209523.
368*795d594fSAndroid Build Coastguard Worker           LOG(WARNING) << "Deferring native library unloading due to contention";
369*795d594fSAndroid Build Coastguard Worker           return;
370*795d594fSAndroid Build Coastguard Worker         }
371*795d594fSAndroid Build Coastguard Worker         ScopedTrace("sleep 1 msec for jni_libraries_lock_");
372*795d594fSAndroid Build Coastguard Worker         usleep(1000);
373*795d594fSAndroid Build Coastguard Worker       }
374*795d594fSAndroid Build Coastguard Worker       for (auto it = libraries_.begin(); it != libraries_.end(); ) {
375*795d594fSAndroid Build Coastguard Worker         SharedLibrary* const library = it->second;
376*795d594fSAndroid Build Coastguard Worker         // If class loader is null then it was unloaded, call JNI_OnUnload.
377*795d594fSAndroid Build Coastguard Worker         const jweak class_loader = library->GetClassLoader();
378*795d594fSAndroid Build Coastguard Worker         // If class_loader is a null jobject then it is the boot class loader. We should not unload
379*795d594fSAndroid Build Coastguard Worker         // the native libraries of the boot class loader.
380*795d594fSAndroid Build Coastguard Worker         if (class_loader != nullptr && self->IsJWeakCleared(class_loader)) {
381*795d594fSAndroid Build Coastguard Worker           unload_libraries.push_back(library);
382*795d594fSAndroid Build Coastguard Worker           it = libraries_.erase(it);
383*795d594fSAndroid Build Coastguard Worker         } else {
384*795d594fSAndroid Build Coastguard Worker           ++it;
385*795d594fSAndroid Build Coastguard Worker         }
386*795d594fSAndroid Build Coastguard Worker       }
387*795d594fSAndroid Build Coastguard Worker       Locks::jni_libraries_lock_->ExclusiveUnlock(self);
388*795d594fSAndroid Build Coastguard Worker     }
389*795d594fSAndroid Build Coastguard Worker     ScopedThreadSuspension sts(self, ThreadState::kNative);
390*795d594fSAndroid Build Coastguard Worker     // Do this without holding the jni libraries lock to prevent possible deadlocks.
391*795d594fSAndroid Build Coastguard Worker     UnloadLibraries(self->GetJniEnv()->GetVm(), unload_libraries);
392*795d594fSAndroid Build Coastguard Worker     for (auto library : unload_libraries) {
393*795d594fSAndroid Build Coastguard Worker       delete library;
394*795d594fSAndroid Build Coastguard Worker     }
395*795d594fSAndroid Build Coastguard Worker   }
396*795d594fSAndroid Build Coastguard Worker 
UnloadLibraries(JavaVM * vm,const std::vector<SharedLibrary * > & libraries)397*795d594fSAndroid Build Coastguard Worker   static void UnloadLibraries(JavaVM* vm, const std::vector<SharedLibrary*>& libraries) {
398*795d594fSAndroid Build Coastguard Worker     using JNI_OnUnloadFn = void(*)(JavaVM*, void*);
399*795d594fSAndroid Build Coastguard Worker     for (SharedLibrary* library : libraries) {
400*795d594fSAndroid Build Coastguard Worker       void* const sym = library->FindSymbol("JNI_OnUnload", nullptr, android::kJNICallTypeRegular);
401*795d594fSAndroid Build Coastguard Worker       if (sym == nullptr) {
402*795d594fSAndroid Build Coastguard Worker         VLOG(jni) << "[No JNI_OnUnload found in \"" << library->GetPath() << "\"]";
403*795d594fSAndroid Build Coastguard Worker       } else {
404*795d594fSAndroid Build Coastguard Worker         VLOG(jni) << "[JNI_OnUnload found for \"" << library->GetPath() << "\"]: Calling...";
405*795d594fSAndroid Build Coastguard Worker         JNI_OnUnloadFn jni_on_unload = reinterpret_cast<JNI_OnUnloadFn>(sym);
406*795d594fSAndroid Build Coastguard Worker         jni_on_unload(vm, nullptr);
407*795d594fSAndroid Build Coastguard Worker       }
408*795d594fSAndroid Build Coastguard Worker     }
409*795d594fSAndroid Build Coastguard Worker   }
410*795d594fSAndroid Build Coastguard Worker 
411*795d594fSAndroid Build Coastguard Worker  private:
412*795d594fSAndroid Build Coastguard Worker   AllocationTrackingSafeMap<std::string, SharedLibrary*, kAllocatorTagJNILibraries> libraries_
413*795d594fSAndroid Build Coastguard Worker       GUARDED_BY(Locks::jni_libraries_lock_);
414*795d594fSAndroid Build Coastguard Worker };
415*795d594fSAndroid Build Coastguard Worker 
416*795d594fSAndroid Build Coastguard Worker class JII {
417*795d594fSAndroid Build Coastguard Worker  public:
DestroyJavaVM(JavaVM * vm)418*795d594fSAndroid Build Coastguard Worker   static jint DestroyJavaVM(JavaVM* vm) {
419*795d594fSAndroid Build Coastguard Worker     if (vm == nullptr) {
420*795d594fSAndroid Build Coastguard Worker       return JNI_ERR;
421*795d594fSAndroid Build Coastguard Worker     }
422*795d594fSAndroid Build Coastguard Worker     JavaVMExt* raw_vm = reinterpret_cast<JavaVMExt*>(vm);
423*795d594fSAndroid Build Coastguard Worker 
424*795d594fSAndroid Build Coastguard Worker     // Wait for all non-dameon threads to terminate before we start destroying
425*795d594fSAndroid Build Coastguard Worker     // bits of the runtime. Thread list deletion will repeat this in case more
426*795d594fSAndroid Build Coastguard Worker     // threads are created by daemons in the meantime.
427*795d594fSAndroid Build Coastguard Worker     raw_vm->GetRuntime()->GetThreadList()
428*795d594fSAndroid Build Coastguard Worker           ->WaitForOtherNonDaemonThreadsToExit(/*check_no_birth=*/ false);
429*795d594fSAndroid Build Coastguard Worker 
430*795d594fSAndroid Build Coastguard Worker     delete raw_vm->GetRuntime();
431*795d594fSAndroid Build Coastguard Worker     android::ResetNativeLoader();
432*795d594fSAndroid Build Coastguard Worker     return JNI_OK;
433*795d594fSAndroid Build Coastguard Worker   }
434*795d594fSAndroid Build Coastguard Worker 
AttachCurrentThread(JavaVM * vm,JNIEnv ** p_env,void * thr_args)435*795d594fSAndroid Build Coastguard Worker   static jint AttachCurrentThread(JavaVM* vm, JNIEnv** p_env, void* thr_args) {
436*795d594fSAndroid Build Coastguard Worker     return AttachCurrentThreadInternal(vm, p_env, thr_args, false);
437*795d594fSAndroid Build Coastguard Worker   }
438*795d594fSAndroid Build Coastguard Worker 
AttachCurrentThreadAsDaemon(JavaVM * vm,JNIEnv ** p_env,void * thr_args)439*795d594fSAndroid Build Coastguard Worker   static jint AttachCurrentThreadAsDaemon(JavaVM* vm, JNIEnv** p_env, void* thr_args) {
440*795d594fSAndroid Build Coastguard Worker     return AttachCurrentThreadInternal(vm, p_env, thr_args, true);
441*795d594fSAndroid Build Coastguard Worker   }
442*795d594fSAndroid Build Coastguard Worker 
DetachCurrentThread(JavaVM * vm)443*795d594fSAndroid Build Coastguard Worker   static jint DetachCurrentThread(JavaVM* vm) {
444*795d594fSAndroid Build Coastguard Worker     if (vm == nullptr || Thread::Current() == nullptr) {
445*795d594fSAndroid Build Coastguard Worker       return JNI_ERR;
446*795d594fSAndroid Build Coastguard Worker     }
447*795d594fSAndroid Build Coastguard Worker     JavaVMExt* raw_vm = reinterpret_cast<JavaVMExt*>(vm);
448*795d594fSAndroid Build Coastguard Worker     Runtime* runtime = raw_vm->GetRuntime();
449*795d594fSAndroid Build Coastguard Worker     runtime->DetachCurrentThread();
450*795d594fSAndroid Build Coastguard Worker     return JNI_OK;
451*795d594fSAndroid Build Coastguard Worker   }
452*795d594fSAndroid Build Coastguard Worker 
GetEnv(JavaVM * vm,void ** env,jint version)453*795d594fSAndroid Build Coastguard Worker   static jint GetEnv(JavaVM* vm, void** env, jint version) {
454*795d594fSAndroid Build Coastguard Worker     if (vm == nullptr || env == nullptr) {
455*795d594fSAndroid Build Coastguard Worker       return JNI_ERR;
456*795d594fSAndroid Build Coastguard Worker     }
457*795d594fSAndroid Build Coastguard Worker     Thread* thread = Thread::Current();
458*795d594fSAndroid Build Coastguard Worker     if (thread == nullptr) {
459*795d594fSAndroid Build Coastguard Worker       *env = nullptr;
460*795d594fSAndroid Build Coastguard Worker       return JNI_EDETACHED;
461*795d594fSAndroid Build Coastguard Worker     }
462*795d594fSAndroid Build Coastguard Worker     JavaVMExt* raw_vm = reinterpret_cast<JavaVMExt*>(vm);
463*795d594fSAndroid Build Coastguard Worker     return raw_vm->HandleGetEnv(env, version);
464*795d594fSAndroid Build Coastguard Worker   }
465*795d594fSAndroid Build Coastguard Worker 
466*795d594fSAndroid Build Coastguard Worker  private:
AttachCurrentThreadInternal(JavaVM * vm,JNIEnv ** p_env,void * raw_args,bool as_daemon)467*795d594fSAndroid Build Coastguard Worker   static jint AttachCurrentThreadInternal(JavaVM* vm, JNIEnv** p_env, void* raw_args, bool as_daemon) {
468*795d594fSAndroid Build Coastguard Worker     if (vm == nullptr || p_env == nullptr) {
469*795d594fSAndroid Build Coastguard Worker       return JNI_ERR;
470*795d594fSAndroid Build Coastguard Worker     }
471*795d594fSAndroid Build Coastguard Worker 
472*795d594fSAndroid Build Coastguard Worker     // Return immediately if we're already attached.
473*795d594fSAndroid Build Coastguard Worker     Thread* self = Thread::Current();
474*795d594fSAndroid Build Coastguard Worker     if (self != nullptr) {
475*795d594fSAndroid Build Coastguard Worker       *p_env = self->GetJniEnv();
476*795d594fSAndroid Build Coastguard Worker       return JNI_OK;
477*795d594fSAndroid Build Coastguard Worker     }
478*795d594fSAndroid Build Coastguard Worker 
479*795d594fSAndroid Build Coastguard Worker     Runtime* runtime = reinterpret_cast<JavaVMExt*>(vm)->GetRuntime();
480*795d594fSAndroid Build Coastguard Worker 
481*795d594fSAndroid Build Coastguard Worker     // No threads allowed in zygote mode.
482*795d594fSAndroid Build Coastguard Worker     if (runtime->IsZygote()) {
483*795d594fSAndroid Build Coastguard Worker       LOG(ERROR) << "Attempt to attach a thread in the zygote";
484*795d594fSAndroid Build Coastguard Worker       return JNI_ERR;
485*795d594fSAndroid Build Coastguard Worker     }
486*795d594fSAndroid Build Coastguard Worker 
487*795d594fSAndroid Build Coastguard Worker     JavaVMAttachArgs* args = static_cast<JavaVMAttachArgs*>(raw_args);
488*795d594fSAndroid Build Coastguard Worker     const char* thread_name = nullptr;
489*795d594fSAndroid Build Coastguard Worker     jobject thread_group = nullptr;
490*795d594fSAndroid Build Coastguard Worker     if (args != nullptr) {
491*795d594fSAndroid Build Coastguard Worker       if (JavaVMExt::IsBadJniVersion(args->version)) {
492*795d594fSAndroid Build Coastguard Worker         LOG(ERROR) << "Bad JNI version passed to "
493*795d594fSAndroid Build Coastguard Worker                    << (as_daemon ? "AttachCurrentThreadAsDaemon" : "AttachCurrentThread") << ": "
494*795d594fSAndroid Build Coastguard Worker                    << args->version;
495*795d594fSAndroid Build Coastguard Worker         return JNI_EVERSION;
496*795d594fSAndroid Build Coastguard Worker       }
497*795d594fSAndroid Build Coastguard Worker       thread_name = args->name;
498*795d594fSAndroid Build Coastguard Worker       thread_group = args->group;
499*795d594fSAndroid Build Coastguard Worker     }
500*795d594fSAndroid Build Coastguard Worker 
501*795d594fSAndroid Build Coastguard Worker     if (!runtime->AttachCurrentThread(thread_name, as_daemon, thread_group,
502*795d594fSAndroid Build Coastguard Worker                                       !runtime->IsAotCompiler())) {
503*795d594fSAndroid Build Coastguard Worker       *p_env = nullptr;
504*795d594fSAndroid Build Coastguard Worker       return JNI_ERR;
505*795d594fSAndroid Build Coastguard Worker     } else {
506*795d594fSAndroid Build Coastguard Worker       *p_env = Thread::Current()->GetJniEnv();
507*795d594fSAndroid Build Coastguard Worker       return JNI_OK;
508*795d594fSAndroid Build Coastguard Worker     }
509*795d594fSAndroid Build Coastguard Worker   }
510*795d594fSAndroid Build Coastguard Worker };
511*795d594fSAndroid Build Coastguard Worker 
512*795d594fSAndroid Build Coastguard Worker const JNIInvokeInterface gJniInvokeInterface = {
513*795d594fSAndroid Build Coastguard Worker   nullptr,  // reserved0
514*795d594fSAndroid Build Coastguard Worker   nullptr,  // reserved1
515*795d594fSAndroid Build Coastguard Worker   nullptr,  // reserved2
516*795d594fSAndroid Build Coastguard Worker   JII::DestroyJavaVM,
517*795d594fSAndroid Build Coastguard Worker   JII::AttachCurrentThread,
518*795d594fSAndroid Build Coastguard Worker   JII::DetachCurrentThread,
519*795d594fSAndroid Build Coastguard Worker   JII::GetEnv,
520*795d594fSAndroid Build Coastguard Worker   JII::AttachCurrentThreadAsDaemon
521*795d594fSAndroid Build Coastguard Worker };
522*795d594fSAndroid Build Coastguard Worker 
JavaVMExt(Runtime * runtime,const RuntimeArgumentMap & runtime_options)523*795d594fSAndroid Build Coastguard Worker JavaVMExt::JavaVMExt(Runtime* runtime, const RuntimeArgumentMap& runtime_options)
524*795d594fSAndroid Build Coastguard Worker     : runtime_(runtime),
525*795d594fSAndroid Build Coastguard Worker       check_jni_abort_hook_(nullptr),
526*795d594fSAndroid Build Coastguard Worker       check_jni_abort_hook_data_(nullptr),
527*795d594fSAndroid Build Coastguard Worker       check_jni_(false),  // Initialized properly in the constructor body below.
528*795d594fSAndroid Build Coastguard Worker       force_copy_(runtime_options.Exists(RuntimeArgumentMap::JniOptsForceCopy)),
529*795d594fSAndroid Build Coastguard Worker       tracing_enabled_(runtime_options.Exists(RuntimeArgumentMap::JniTrace)
530*795d594fSAndroid Build Coastguard Worker                        || VLOG_IS_ON(third_party_jni)),
531*795d594fSAndroid Build Coastguard Worker       trace_(runtime_options.GetOrDefault(RuntimeArgumentMap::JniTrace)),
532*795d594fSAndroid Build Coastguard Worker       globals_(kGlobal),
533*795d594fSAndroid Build Coastguard Worker       libraries_(new Libraries),
534*795d594fSAndroid Build Coastguard Worker       unchecked_functions_(&gJniInvokeInterface),
535*795d594fSAndroid Build Coastguard Worker       weak_globals_(kWeakGlobal),
536*795d594fSAndroid Build Coastguard Worker       allow_accessing_weak_globals_(true),
537*795d594fSAndroid Build Coastguard Worker       weak_globals_add_condition_("weak globals add condition",
538*795d594fSAndroid Build Coastguard Worker                                   (CHECK(Locks::jni_weak_globals_lock_ != nullptr),
539*795d594fSAndroid Build Coastguard Worker                                    *Locks::jni_weak_globals_lock_)),
540*795d594fSAndroid Build Coastguard Worker       env_hooks_lock_("environment hooks lock", art::kGenericBottomLock),
541*795d594fSAndroid Build Coastguard Worker       env_hooks_(),
542*795d594fSAndroid Build Coastguard Worker       enable_allocation_tracking_delta_(
543*795d594fSAndroid Build Coastguard Worker           runtime_options.GetOrDefault(RuntimeArgumentMap::GlobalRefAllocStackTraceLimit)),
544*795d594fSAndroid Build Coastguard Worker       allocation_tracking_enabled_(false),
545*795d594fSAndroid Build Coastguard Worker       old_allocation_tracking_state_(false) {
546*795d594fSAndroid Build Coastguard Worker   functions = unchecked_functions_;
547*795d594fSAndroid Build Coastguard Worker   SetCheckJniEnabled(runtime_options.Exists(RuntimeArgumentMap::CheckJni) || kIsDebugBuild);
548*795d594fSAndroid Build Coastguard Worker }
549*795d594fSAndroid Build Coastguard Worker 
Initialize(std::string * error_msg)550*795d594fSAndroid Build Coastguard Worker bool JavaVMExt::Initialize(std::string* error_msg) {
551*795d594fSAndroid Build Coastguard Worker   return globals_.Initialize(kGlobalsMax, error_msg) &&
552*795d594fSAndroid Build Coastguard Worker          weak_globals_.Initialize(kWeakGlobalsMax, error_msg);
553*795d594fSAndroid Build Coastguard Worker }
554*795d594fSAndroid Build Coastguard Worker 
~JavaVMExt()555*795d594fSAndroid Build Coastguard Worker JavaVMExt::~JavaVMExt() {
556*795d594fSAndroid Build Coastguard Worker   UnloadBootNativeLibraries();
557*795d594fSAndroid Build Coastguard Worker }
558*795d594fSAndroid Build Coastguard Worker 
Create(Runtime * runtime,const RuntimeArgumentMap & runtime_options,std::string * error_msg)559*795d594fSAndroid Build Coastguard Worker std::unique_ptr<JavaVMExt> JavaVMExt::Create(Runtime* runtime,
560*795d594fSAndroid Build Coastguard Worker                                              const RuntimeArgumentMap& runtime_options,
561*795d594fSAndroid Build Coastguard Worker                                              std::string* error_msg) {
562*795d594fSAndroid Build Coastguard Worker   std::unique_ptr<JavaVMExt> java_vm(new JavaVMExt(runtime, runtime_options));
563*795d594fSAndroid Build Coastguard Worker   if (!java_vm->Initialize(error_msg)) {
564*795d594fSAndroid Build Coastguard Worker     return nullptr;
565*795d594fSAndroid Build Coastguard Worker   }
566*795d594fSAndroid Build Coastguard Worker   return java_vm;
567*795d594fSAndroid Build Coastguard Worker }
568*795d594fSAndroid Build Coastguard Worker 
HandleGetEnv(void ** env,jint version)569*795d594fSAndroid Build Coastguard Worker jint JavaVMExt::HandleGetEnv(/*out*/void** env, jint version) {
570*795d594fSAndroid Build Coastguard Worker   std::vector<GetEnvHook> env_hooks;
571*795d594fSAndroid Build Coastguard Worker   {
572*795d594fSAndroid Build Coastguard Worker     ReaderMutexLock rmu(Thread::Current(), env_hooks_lock_);
573*795d594fSAndroid Build Coastguard Worker     env_hooks.assign(env_hooks_.begin(), env_hooks_.end());
574*795d594fSAndroid Build Coastguard Worker   }
575*795d594fSAndroid Build Coastguard Worker   for (GetEnvHook hook : env_hooks) {
576*795d594fSAndroid Build Coastguard Worker     jint res = hook(this, env, version);
577*795d594fSAndroid Build Coastguard Worker     if (res == JNI_OK) {
578*795d594fSAndroid Build Coastguard Worker       return JNI_OK;
579*795d594fSAndroid Build Coastguard Worker     } else if (res != JNI_EVERSION) {
580*795d594fSAndroid Build Coastguard Worker       LOG(ERROR) << "Error returned from a plugin GetEnv handler! " << res;
581*795d594fSAndroid Build Coastguard Worker       return res;
582*795d594fSAndroid Build Coastguard Worker     }
583*795d594fSAndroid Build Coastguard Worker   }
584*795d594fSAndroid Build Coastguard Worker   LOG(ERROR) << "Bad JNI version passed to GetEnv: " << version;
585*795d594fSAndroid Build Coastguard Worker   return JNI_EVERSION;
586*795d594fSAndroid Build Coastguard Worker }
587*795d594fSAndroid Build Coastguard Worker 
588*795d594fSAndroid Build Coastguard Worker // Add a hook to handle getting environments from the GetEnv call.
AddEnvironmentHook(GetEnvHook hook)589*795d594fSAndroid Build Coastguard Worker void JavaVMExt::AddEnvironmentHook(GetEnvHook hook) {
590*795d594fSAndroid Build Coastguard Worker   CHECK(hook != nullptr) << "environment hooks shouldn't be null!";
591*795d594fSAndroid Build Coastguard Worker   WriterMutexLock wmu(Thread::Current(), env_hooks_lock_);
592*795d594fSAndroid Build Coastguard Worker   env_hooks_.push_back(hook);
593*795d594fSAndroid Build Coastguard Worker }
594*795d594fSAndroid Build Coastguard Worker 
JniAbort(const char * jni_function_name,const char * msg)595*795d594fSAndroid Build Coastguard Worker void JavaVMExt::JniAbort(const char* jni_function_name, const char* msg) {
596*795d594fSAndroid Build Coastguard Worker   Thread* self = Thread::Current();
597*795d594fSAndroid Build Coastguard Worker   ScopedObjectAccess soa(self);
598*795d594fSAndroid Build Coastguard Worker   ArtMethod* current_method = self->GetCurrentMethod(nullptr);
599*795d594fSAndroid Build Coastguard Worker 
600*795d594fSAndroid Build Coastguard Worker   std::ostringstream os;
601*795d594fSAndroid Build Coastguard Worker   os << "JNI DETECTED ERROR IN APPLICATION: " << msg;
602*795d594fSAndroid Build Coastguard Worker 
603*795d594fSAndroid Build Coastguard Worker   if (jni_function_name != nullptr) {
604*795d594fSAndroid Build Coastguard Worker     os << "\n    in call to " << jni_function_name;
605*795d594fSAndroid Build Coastguard Worker   }
606*795d594fSAndroid Build Coastguard Worker   // TODO: is this useful given that we're about to dump the calling thread's stack?
607*795d594fSAndroid Build Coastguard Worker   if (current_method != nullptr) {
608*795d594fSAndroid Build Coastguard Worker     os << "\n    from " << current_method->PrettyMethod();
609*795d594fSAndroid Build Coastguard Worker   }
610*795d594fSAndroid Build Coastguard Worker 
611*795d594fSAndroid Build Coastguard Worker   if (check_jni_abort_hook_ != nullptr) {
612*795d594fSAndroid Build Coastguard Worker     check_jni_abort_hook_(check_jni_abort_hook_data_, os.str());
613*795d594fSAndroid Build Coastguard Worker   } else {
614*795d594fSAndroid Build Coastguard Worker     // Ensure that we get a native stack trace for this thread.
615*795d594fSAndroid Build Coastguard Worker     ScopedThreadSuspension sts(self, ThreadState::kNative);
616*795d594fSAndroid Build Coastguard Worker     LOG(FATAL) << os.str();
617*795d594fSAndroid Build Coastguard Worker     UNREACHABLE();
618*795d594fSAndroid Build Coastguard Worker   }
619*795d594fSAndroid Build Coastguard Worker }
620*795d594fSAndroid Build Coastguard Worker 
JniAbortV(const char * jni_function_name,const char * fmt,va_list ap)621*795d594fSAndroid Build Coastguard Worker void JavaVMExt::JniAbortV(const char* jni_function_name, const char* fmt, va_list ap) {
622*795d594fSAndroid Build Coastguard Worker   std::string msg;
623*795d594fSAndroid Build Coastguard Worker   StringAppendV(&msg, fmt, ap);
624*795d594fSAndroid Build Coastguard Worker   JniAbort(jni_function_name, msg.c_str());
625*795d594fSAndroid Build Coastguard Worker }
626*795d594fSAndroid Build Coastguard Worker 
JniAbortF(const char * jni_function_name,const char * fmt,...)627*795d594fSAndroid Build Coastguard Worker void JavaVMExt::JniAbortF(const char* jni_function_name, const char* fmt, ...) {
628*795d594fSAndroid Build Coastguard Worker   va_list args;
629*795d594fSAndroid Build Coastguard Worker   va_start(args, fmt);
630*795d594fSAndroid Build Coastguard Worker   JniAbortV(jni_function_name, fmt, args);
631*795d594fSAndroid Build Coastguard Worker   va_end(args);
632*795d594fSAndroid Build Coastguard Worker }
633*795d594fSAndroid Build Coastguard Worker 
ShouldTrace(ArtMethod * method)634*795d594fSAndroid Build Coastguard Worker bool JavaVMExt::ShouldTrace(ArtMethod* method) {
635*795d594fSAndroid Build Coastguard Worker   // Fast where no tracing is enabled.
636*795d594fSAndroid Build Coastguard Worker   if (trace_.empty() && !VLOG_IS_ON(third_party_jni)) {
637*795d594fSAndroid Build Coastguard Worker     return false;
638*795d594fSAndroid Build Coastguard Worker   }
639*795d594fSAndroid Build Coastguard Worker   // Perform checks based on class name.
640*795d594fSAndroid Build Coastguard Worker   std::string_view class_name = method->GetDeclaringClassDescriptorView();
641*795d594fSAndroid Build Coastguard Worker   if (!trace_.empty() && class_name.find(trace_) != std::string_view::npos) {
642*795d594fSAndroid Build Coastguard Worker     return true;
643*795d594fSAndroid Build Coastguard Worker   }
644*795d594fSAndroid Build Coastguard Worker   if (!VLOG_IS_ON(third_party_jni)) {
645*795d594fSAndroid Build Coastguard Worker     return false;
646*795d594fSAndroid Build Coastguard Worker   }
647*795d594fSAndroid Build Coastguard Worker   // Return true if we're trying to log all third-party JNI activity and 'method' doesn't look
648*795d594fSAndroid Build Coastguard Worker   // like part of Android.
649*795d594fSAndroid Build Coastguard Worker   static const char* const gBuiltInPrefixes[] = {
650*795d594fSAndroid Build Coastguard Worker       "Landroid/",
651*795d594fSAndroid Build Coastguard Worker       "Lcom/android/",
652*795d594fSAndroid Build Coastguard Worker       "Lcom/google/android/",
653*795d594fSAndroid Build Coastguard Worker       "Ldalvik/",
654*795d594fSAndroid Build Coastguard Worker       "Ljava/",
655*795d594fSAndroid Build Coastguard Worker       "Ljavax/",
656*795d594fSAndroid Build Coastguard Worker       "Llibcore/",
657*795d594fSAndroid Build Coastguard Worker       "Lorg/apache/harmony/",
658*795d594fSAndroid Build Coastguard Worker   };
659*795d594fSAndroid Build Coastguard Worker   for (size_t i = 0; i < arraysize(gBuiltInPrefixes); ++i) {
660*795d594fSAndroid Build Coastguard Worker     if (class_name.starts_with(gBuiltInPrefixes[i])) {
661*795d594fSAndroid Build Coastguard Worker       return false;
662*795d594fSAndroid Build Coastguard Worker     }
663*795d594fSAndroid Build Coastguard Worker   }
664*795d594fSAndroid Build Coastguard Worker   return true;
665*795d594fSAndroid Build Coastguard Worker }
666*795d594fSAndroid Build Coastguard Worker 
CheckGlobalRefAllocationTracking()667*795d594fSAndroid Build Coastguard Worker void JavaVMExt::CheckGlobalRefAllocationTracking() {
668*795d594fSAndroid Build Coastguard Worker   if (LIKELY(enable_allocation_tracking_delta_ == 0)) {
669*795d594fSAndroid Build Coastguard Worker     return;
670*795d594fSAndroid Build Coastguard Worker   }
671*795d594fSAndroid Build Coastguard Worker   size_t simple_free_capacity = globals_.FreeCapacity();
672*795d594fSAndroid Build Coastguard Worker   if (UNLIKELY(simple_free_capacity <= enable_allocation_tracking_delta_)) {
673*795d594fSAndroid Build Coastguard Worker     if (!allocation_tracking_enabled_) {
674*795d594fSAndroid Build Coastguard Worker       LOG(WARNING) << "Global reference storage appears close to exhaustion, program termination "
675*795d594fSAndroid Build Coastguard Worker                    << "may be imminent. Enabling allocation tracking to improve abort diagnostics. "
676*795d594fSAndroid Build Coastguard Worker                    << "This will result in program slow-down.";
677*795d594fSAndroid Build Coastguard Worker 
678*795d594fSAndroid Build Coastguard Worker       old_allocation_tracking_state_ = runtime_->GetHeap()->IsAllocTrackingEnabled();
679*795d594fSAndroid Build Coastguard Worker       if (!old_allocation_tracking_state_) {
680*795d594fSAndroid Build Coastguard Worker         // Need to be guaranteed suspended.
681*795d594fSAndroid Build Coastguard Worker         ScopedObjectAccess soa(Thread::Current());
682*795d594fSAndroid Build Coastguard Worker         ScopedThreadSuspension sts(soa.Self(), ThreadState::kNative);
683*795d594fSAndroid Build Coastguard Worker         gc::AllocRecordObjectMap::SetAllocTrackingEnabled(true);
684*795d594fSAndroid Build Coastguard Worker       }
685*795d594fSAndroid Build Coastguard Worker       allocation_tracking_enabled_ = true;
686*795d594fSAndroid Build Coastguard Worker     }
687*795d594fSAndroid Build Coastguard Worker   } else {
688*795d594fSAndroid Build Coastguard Worker     if (UNLIKELY(allocation_tracking_enabled_)) {
689*795d594fSAndroid Build Coastguard Worker       if (!old_allocation_tracking_state_) {
690*795d594fSAndroid Build Coastguard Worker         // Need to be guaranteed suspended.
691*795d594fSAndroid Build Coastguard Worker         ScopedObjectAccess soa(Thread::Current());
692*795d594fSAndroid Build Coastguard Worker         ScopedThreadSuspension sts(soa.Self(), ThreadState::kNative);
693*795d594fSAndroid Build Coastguard Worker         gc::AllocRecordObjectMap::SetAllocTrackingEnabled(false);
694*795d594fSAndroid Build Coastguard Worker       }
695*795d594fSAndroid Build Coastguard Worker       allocation_tracking_enabled_ = false;
696*795d594fSAndroid Build Coastguard Worker     }
697*795d594fSAndroid Build Coastguard Worker   }
698*795d594fSAndroid Build Coastguard Worker }
699*795d594fSAndroid Build Coastguard Worker 
MaybeTraceGlobals()700*795d594fSAndroid Build Coastguard Worker void JavaVMExt::MaybeTraceGlobals() {
701*795d594fSAndroid Build Coastguard Worker   if (global_ref_report_counter_++ == kGlobalRefReportInterval) {
702*795d594fSAndroid Build Coastguard Worker     global_ref_report_counter_ = 1;
703*795d594fSAndroid Build Coastguard Worker     ATraceIntegerValue("JNI Global Refs", globals_.NEntriesForGlobal());
704*795d594fSAndroid Build Coastguard Worker   }
705*795d594fSAndroid Build Coastguard Worker }
706*795d594fSAndroid Build Coastguard Worker 
MaybeTraceWeakGlobals()707*795d594fSAndroid Build Coastguard Worker void JavaVMExt::MaybeTraceWeakGlobals() {
708*795d594fSAndroid Build Coastguard Worker   if (weak_global_ref_report_counter_++ == kGlobalRefReportInterval) {
709*795d594fSAndroid Build Coastguard Worker     weak_global_ref_report_counter_ = 1;
710*795d594fSAndroid Build Coastguard Worker     ATraceIntegerValue("JNI Weak Global Refs", weak_globals_.NEntriesForGlobal());
711*795d594fSAndroid Build Coastguard Worker   }
712*795d594fSAndroid Build Coastguard Worker }
713*795d594fSAndroid Build Coastguard Worker 
AddGlobalRef(Thread * self,ObjPtr<mirror::Object> obj)714*795d594fSAndroid Build Coastguard Worker jobject JavaVMExt::AddGlobalRef(Thread* self, ObjPtr<mirror::Object> obj) {
715*795d594fSAndroid Build Coastguard Worker   // Check for null after decoding the object to handle cleared weak globals.
716*795d594fSAndroid Build Coastguard Worker   if (obj == nullptr) {
717*795d594fSAndroid Build Coastguard Worker     return nullptr;
718*795d594fSAndroid Build Coastguard Worker   }
719*795d594fSAndroid Build Coastguard Worker   IndirectRef ref;
720*795d594fSAndroid Build Coastguard Worker   std::string error_msg;
721*795d594fSAndroid Build Coastguard Worker   {
722*795d594fSAndroid Build Coastguard Worker     WriterMutexLock mu(self, *Locks::jni_globals_lock_);
723*795d594fSAndroid Build Coastguard Worker     ref = globals_.Add(obj, &error_msg);
724*795d594fSAndroid Build Coastguard Worker     MaybeTraceGlobals();
725*795d594fSAndroid Build Coastguard Worker   }
726*795d594fSAndroid Build Coastguard Worker   if (UNLIKELY(ref == nullptr)) {
727*795d594fSAndroid Build Coastguard Worker     LOG(FATAL) << error_msg;
728*795d594fSAndroid Build Coastguard Worker     UNREACHABLE();
729*795d594fSAndroid Build Coastguard Worker   }
730*795d594fSAndroid Build Coastguard Worker   CheckGlobalRefAllocationTracking();
731*795d594fSAndroid Build Coastguard Worker   return reinterpret_cast<jobject>(ref);
732*795d594fSAndroid Build Coastguard Worker }
733*795d594fSAndroid Build Coastguard Worker 
WaitForWeakGlobalsAccess(Thread * self)734*795d594fSAndroid Build Coastguard Worker void JavaVMExt::WaitForWeakGlobalsAccess(Thread* self) {
735*795d594fSAndroid Build Coastguard Worker   if (UNLIKELY(!MayAccessWeakGlobals(self))) {
736*795d594fSAndroid Build Coastguard Worker     ATraceBegin("Blocking on WeakGlobal access");
737*795d594fSAndroid Build Coastguard Worker     do {
738*795d594fSAndroid Build Coastguard Worker       // Check and run the empty checkpoint before blocking so the empty checkpoint will work in the
739*795d594fSAndroid Build Coastguard Worker       // presence of threads blocking for weak ref access.
740*795d594fSAndroid Build Coastguard Worker       self->CheckEmptyCheckpointFromWeakRefAccess(Locks::jni_weak_globals_lock_);
741*795d594fSAndroid Build Coastguard Worker       weak_globals_add_condition_.WaitHoldingLocks(self);
742*795d594fSAndroid Build Coastguard Worker     } while (!MayAccessWeakGlobals(self));
743*795d594fSAndroid Build Coastguard Worker     ATraceEnd();
744*795d594fSAndroid Build Coastguard Worker   }
745*795d594fSAndroid Build Coastguard Worker }
746*795d594fSAndroid Build Coastguard Worker 
AddWeakGlobalRef(Thread * self,ObjPtr<mirror::Object> obj)747*795d594fSAndroid Build Coastguard Worker jweak JavaVMExt::AddWeakGlobalRef(Thread* self, ObjPtr<mirror::Object> obj) {
748*795d594fSAndroid Build Coastguard Worker   if (obj == nullptr) {
749*795d594fSAndroid Build Coastguard Worker     return nullptr;
750*795d594fSAndroid Build Coastguard Worker   }
751*795d594fSAndroid Build Coastguard Worker   MutexLock mu(self, *Locks::jni_weak_globals_lock_);
752*795d594fSAndroid Build Coastguard Worker   // CMS needs this to block for concurrent reference processing because an object allocated during
753*795d594fSAndroid Build Coastguard Worker   // the GC won't be marked and concurrent reference processing would incorrectly clear the JNI weak
754*795d594fSAndroid Build Coastguard Worker   // ref. But CC (gUseReadBarrier == true) doesn't because of the to-space invariant.
755*795d594fSAndroid Build Coastguard Worker   if (!gUseReadBarrier) {
756*795d594fSAndroid Build Coastguard Worker     WaitForWeakGlobalsAccess(self);
757*795d594fSAndroid Build Coastguard Worker   }
758*795d594fSAndroid Build Coastguard Worker   std::string error_msg;
759*795d594fSAndroid Build Coastguard Worker   IndirectRef ref = weak_globals_.Add(obj, &error_msg);
760*795d594fSAndroid Build Coastguard Worker   MaybeTraceWeakGlobals();
761*795d594fSAndroid Build Coastguard Worker   if (UNLIKELY(ref == nullptr)) {
762*795d594fSAndroid Build Coastguard Worker     LOG(FATAL) << error_msg;
763*795d594fSAndroid Build Coastguard Worker     UNREACHABLE();
764*795d594fSAndroid Build Coastguard Worker   }
765*795d594fSAndroid Build Coastguard Worker   return reinterpret_cast<jweak>(ref);
766*795d594fSAndroid Build Coastguard Worker }
767*795d594fSAndroid Build Coastguard Worker 
DeleteGlobalRef(Thread * self,jobject obj)768*795d594fSAndroid Build Coastguard Worker void JavaVMExt::DeleteGlobalRef(Thread* self, jobject obj) {
769*795d594fSAndroid Build Coastguard Worker   if (obj == nullptr) {
770*795d594fSAndroid Build Coastguard Worker     return;
771*795d594fSAndroid Build Coastguard Worker   }
772*795d594fSAndroid Build Coastguard Worker   {
773*795d594fSAndroid Build Coastguard Worker     WriterMutexLock mu(self, *Locks::jni_globals_lock_);
774*795d594fSAndroid Build Coastguard Worker     if (!globals_.Remove(obj)) {
775*795d594fSAndroid Build Coastguard Worker       LOG(WARNING) << "JNI WARNING: DeleteGlobalRef(" << obj << ") "
776*795d594fSAndroid Build Coastguard Worker                    << "failed to find entry";
777*795d594fSAndroid Build Coastguard Worker     }
778*795d594fSAndroid Build Coastguard Worker     MaybeTraceGlobals();
779*795d594fSAndroid Build Coastguard Worker   }
780*795d594fSAndroid Build Coastguard Worker   CheckGlobalRefAllocationTracking();
781*795d594fSAndroid Build Coastguard Worker }
782*795d594fSAndroid Build Coastguard Worker 
DeleteWeakGlobalRef(Thread * self,jweak obj)783*795d594fSAndroid Build Coastguard Worker void JavaVMExt::DeleteWeakGlobalRef(Thread* self, jweak obj) {
784*795d594fSAndroid Build Coastguard Worker   if (obj == nullptr) {
785*795d594fSAndroid Build Coastguard Worker     return;
786*795d594fSAndroid Build Coastguard Worker   }
787*795d594fSAndroid Build Coastguard Worker   MutexLock mu(self, *Locks::jni_weak_globals_lock_);
788*795d594fSAndroid Build Coastguard Worker   if (!weak_globals_.Remove(obj)) {
789*795d594fSAndroid Build Coastguard Worker     LOG(WARNING) << "JNI WARNING: DeleteWeakGlobalRef(" << obj << ") "
790*795d594fSAndroid Build Coastguard Worker                  << "failed to find entry";
791*795d594fSAndroid Build Coastguard Worker   }
792*795d594fSAndroid Build Coastguard Worker   MaybeTraceWeakGlobals();
793*795d594fSAndroid Build Coastguard Worker }
794*795d594fSAndroid Build Coastguard Worker 
ThreadEnableCheckJni(Thread * thread,void * arg)795*795d594fSAndroid Build Coastguard Worker static void ThreadEnableCheckJni(Thread* thread, void* arg) {
796*795d594fSAndroid Build Coastguard Worker   bool* check_jni = reinterpret_cast<bool*>(arg);
797*795d594fSAndroid Build Coastguard Worker   thread->GetJniEnv()->SetCheckJniEnabled(*check_jni);
798*795d594fSAndroid Build Coastguard Worker }
799*795d594fSAndroid Build Coastguard Worker 
SetCheckJniEnabled(bool enabled)800*795d594fSAndroid Build Coastguard Worker bool JavaVMExt::SetCheckJniEnabled(bool enabled) {
801*795d594fSAndroid Build Coastguard Worker   bool old_check_jni = check_jni_;
802*795d594fSAndroid Build Coastguard Worker   check_jni_ = enabled;
803*795d594fSAndroid Build Coastguard Worker   functions = enabled ? GetCheckJniInvokeInterface() : unchecked_functions_;
804*795d594fSAndroid Build Coastguard Worker   MutexLock mu(Thread::Current(), *Locks::thread_list_lock_);
805*795d594fSAndroid Build Coastguard Worker   runtime_->GetThreadList()->ForEach(ThreadEnableCheckJni, &check_jni_);
806*795d594fSAndroid Build Coastguard Worker   return old_check_jni;
807*795d594fSAndroid Build Coastguard Worker }
808*795d594fSAndroid Build Coastguard Worker 
DumpForSigQuit(std::ostream & os)809*795d594fSAndroid Build Coastguard Worker void JavaVMExt::DumpForSigQuit(std::ostream& os) {
810*795d594fSAndroid Build Coastguard Worker   os << "JNI: CheckJNI is " << (check_jni_ ? "on" : "off");
811*795d594fSAndroid Build Coastguard Worker   if (force_copy_) {
812*795d594fSAndroid Build Coastguard Worker     os << " (with forcecopy)";
813*795d594fSAndroid Build Coastguard Worker   }
814*795d594fSAndroid Build Coastguard Worker   Thread* self = Thread::Current();
815*795d594fSAndroid Build Coastguard Worker   {
816*795d594fSAndroid Build Coastguard Worker     ReaderMutexLock mu(self, *Locks::jni_globals_lock_);
817*795d594fSAndroid Build Coastguard Worker     os << "; globals=" << globals_.Capacity();
818*795d594fSAndroid Build Coastguard Worker   }
819*795d594fSAndroid Build Coastguard Worker   {
820*795d594fSAndroid Build Coastguard Worker     MutexLock mu(self, *Locks::jni_weak_globals_lock_);
821*795d594fSAndroid Build Coastguard Worker     if (weak_globals_.Capacity() > 0) {
822*795d594fSAndroid Build Coastguard Worker       os << " (plus " << weak_globals_.Capacity() << " weak)";
823*795d594fSAndroid Build Coastguard Worker     }
824*795d594fSAndroid Build Coastguard Worker   }
825*795d594fSAndroid Build Coastguard Worker   os << '\n';
826*795d594fSAndroid Build Coastguard Worker 
827*795d594fSAndroid Build Coastguard Worker   {
828*795d594fSAndroid Build Coastguard Worker     MutexLock mu(self, *Locks::jni_libraries_lock_);
829*795d594fSAndroid Build Coastguard Worker     os << "Libraries: " << Dumpable<Libraries>(*libraries_) << " (" << libraries_->size() << ")\n";
830*795d594fSAndroid Build Coastguard Worker   }
831*795d594fSAndroid Build Coastguard Worker }
832*795d594fSAndroid Build Coastguard Worker 
DisallowNewWeakGlobals()833*795d594fSAndroid Build Coastguard Worker void JavaVMExt::DisallowNewWeakGlobals() {
834*795d594fSAndroid Build Coastguard Worker   CHECK(!gUseReadBarrier);
835*795d594fSAndroid Build Coastguard Worker   Thread* const self = Thread::Current();
836*795d594fSAndroid Build Coastguard Worker   MutexLock mu(self, *Locks::jni_weak_globals_lock_);
837*795d594fSAndroid Build Coastguard Worker   // DisallowNewWeakGlobals is only called by CMS during the pause. It is required to have the
838*795d594fSAndroid Build Coastguard Worker   // mutator lock exclusively held so that we don't have any threads in the middle of
839*795d594fSAndroid Build Coastguard Worker   // DecodeWeakGlobal.
840*795d594fSAndroid Build Coastguard Worker   Locks::mutator_lock_->AssertExclusiveHeld(self);
841*795d594fSAndroid Build Coastguard Worker   allow_accessing_weak_globals_.store(false, std::memory_order_seq_cst);
842*795d594fSAndroid Build Coastguard Worker }
843*795d594fSAndroid Build Coastguard Worker 
AllowNewWeakGlobals()844*795d594fSAndroid Build Coastguard Worker void JavaVMExt::AllowNewWeakGlobals() {
845*795d594fSAndroid Build Coastguard Worker   CHECK(!gUseReadBarrier);
846*795d594fSAndroid Build Coastguard Worker   Thread* self = Thread::Current();
847*795d594fSAndroid Build Coastguard Worker   MutexLock mu(self, *Locks::jni_weak_globals_lock_);
848*795d594fSAndroid Build Coastguard Worker   allow_accessing_weak_globals_.store(true, std::memory_order_seq_cst);
849*795d594fSAndroid Build Coastguard Worker   weak_globals_add_condition_.Broadcast(self);
850*795d594fSAndroid Build Coastguard Worker }
851*795d594fSAndroid Build Coastguard Worker 
BroadcastForNewWeakGlobals()852*795d594fSAndroid Build Coastguard Worker void JavaVMExt::BroadcastForNewWeakGlobals() {
853*795d594fSAndroid Build Coastguard Worker   Thread* self = Thread::Current();
854*795d594fSAndroid Build Coastguard Worker   MutexLock mu(self, *Locks::jni_weak_globals_lock_);
855*795d594fSAndroid Build Coastguard Worker   weak_globals_add_condition_.Broadcast(self);
856*795d594fSAndroid Build Coastguard Worker }
857*795d594fSAndroid Build Coastguard Worker 
DecodeGlobal(IndirectRef ref)858*795d594fSAndroid Build Coastguard Worker ObjPtr<mirror::Object> JavaVMExt::DecodeGlobal(IndirectRef ref) {
859*795d594fSAndroid Build Coastguard Worker   return globals_.Get(ref);
860*795d594fSAndroid Build Coastguard Worker }
861*795d594fSAndroid Build Coastguard Worker 
UpdateGlobal(Thread * self,IndirectRef ref,ObjPtr<mirror::Object> result)862*795d594fSAndroid Build Coastguard Worker void JavaVMExt::UpdateGlobal(Thread* self, IndirectRef ref, ObjPtr<mirror::Object> result) {
863*795d594fSAndroid Build Coastguard Worker   WriterMutexLock mu(self, *Locks::jni_globals_lock_);
864*795d594fSAndroid Build Coastguard Worker   globals_.Update(ref, result);
865*795d594fSAndroid Build Coastguard Worker }
866*795d594fSAndroid Build Coastguard Worker 
DecodeWeakGlobal(Thread * self,IndirectRef ref)867*795d594fSAndroid Build Coastguard Worker ObjPtr<mirror::Object> JavaVMExt::DecodeWeakGlobal(Thread* self, IndirectRef ref) {
868*795d594fSAndroid Build Coastguard Worker   // It is safe to access GetWeakRefAccessEnabled without the lock since CC uses checkpoints to call
869*795d594fSAndroid Build Coastguard Worker   // SetWeakRefAccessEnabled, and the other collectors only modify allow_accessing_weak_globals_
870*795d594fSAndroid Build Coastguard Worker   // when the mutators are paused.
871*795d594fSAndroid Build Coastguard Worker   // This only applies in the case where MayAccessWeakGlobals goes from false to true. In the other
872*795d594fSAndroid Build Coastguard Worker   // case, it may be racy, this is benign since DecodeWeakGlobalLocked does the correct behavior
873*795d594fSAndroid Build Coastguard Worker   // if MayAccessWeakGlobals is false.
874*795d594fSAndroid Build Coastguard Worker   DCHECK_EQ(IndirectReferenceTable::GetIndirectRefKind(ref), kWeakGlobal);
875*795d594fSAndroid Build Coastguard Worker   if (LIKELY(MayAccessWeakGlobals(self))) {
876*795d594fSAndroid Build Coastguard Worker     return weak_globals_.Get(ref);
877*795d594fSAndroid Build Coastguard Worker   }
878*795d594fSAndroid Build Coastguard Worker   MutexLock mu(self, *Locks::jni_weak_globals_lock_);
879*795d594fSAndroid Build Coastguard Worker   return DecodeWeakGlobalLocked(self, ref);
880*795d594fSAndroid Build Coastguard Worker }
881*795d594fSAndroid Build Coastguard Worker 
DecodeWeakGlobalLocked(Thread * self,IndirectRef ref)882*795d594fSAndroid Build Coastguard Worker ObjPtr<mirror::Object> JavaVMExt::DecodeWeakGlobalLocked(Thread* self, IndirectRef ref) {
883*795d594fSAndroid Build Coastguard Worker   if (kDebugLocking) {
884*795d594fSAndroid Build Coastguard Worker     Locks::jni_weak_globals_lock_->AssertHeld(self);
885*795d594fSAndroid Build Coastguard Worker   }
886*795d594fSAndroid Build Coastguard Worker   // TODO: Handle the already null case without waiting.
887*795d594fSAndroid Build Coastguard Worker   // TODO: Otherwise we should just wait for kInitMarkingDone, and track which weak globals were
888*795d594fSAndroid Build Coastguard Worker   // marked at that point. We would only need one mark bit per entry in the weak_globals_ table,
889*795d594fSAndroid Build Coastguard Worker   // and a quick pass over that early on during reference processing.
890*795d594fSAndroid Build Coastguard Worker   WaitForWeakGlobalsAccess(self);
891*795d594fSAndroid Build Coastguard Worker   return weak_globals_.Get(ref);
892*795d594fSAndroid Build Coastguard Worker }
893*795d594fSAndroid Build Coastguard Worker 
DecodeWeakGlobalAsStrong(IndirectRef ref)894*795d594fSAndroid Build Coastguard Worker ObjPtr<mirror::Object> JavaVMExt::DecodeWeakGlobalAsStrong(IndirectRef ref) {
895*795d594fSAndroid Build Coastguard Worker   // The target is known to be alive. Simple `Get()` with read barrier is enough.
896*795d594fSAndroid Build Coastguard Worker   return weak_globals_.Get(ref);
897*795d594fSAndroid Build Coastguard Worker }
898*795d594fSAndroid Build Coastguard Worker 
DecodeWeakGlobalDuringShutdown(Thread * self,IndirectRef ref)899*795d594fSAndroid Build Coastguard Worker ObjPtr<mirror::Object> JavaVMExt::DecodeWeakGlobalDuringShutdown(Thread* self, IndirectRef ref) {
900*795d594fSAndroid Build Coastguard Worker   DCHECK_EQ(IndirectReferenceTable::GetIndirectRefKind(ref), kWeakGlobal);
901*795d594fSAndroid Build Coastguard Worker   DCHECK(Runtime::Current()->IsShuttingDown(self));
902*795d594fSAndroid Build Coastguard Worker   if (self != nullptr) {
903*795d594fSAndroid Build Coastguard Worker     return DecodeWeakGlobal(self, ref);
904*795d594fSAndroid Build Coastguard Worker   }
905*795d594fSAndroid Build Coastguard Worker   // self can be null during a runtime shutdown. ~Runtime()->~ClassLinker()->DecodeWeakGlobal().
906*795d594fSAndroid Build Coastguard Worker   if (!gUseReadBarrier) {
907*795d594fSAndroid Build Coastguard Worker     DCHECK(allow_accessing_weak_globals_.load(std::memory_order_seq_cst));
908*795d594fSAndroid Build Coastguard Worker   }
909*795d594fSAndroid Build Coastguard Worker   return weak_globals_.Get(ref);
910*795d594fSAndroid Build Coastguard Worker }
911*795d594fSAndroid Build Coastguard Worker 
IsWeakGlobalCleared(Thread * self,IndirectRef ref)912*795d594fSAndroid Build Coastguard Worker bool JavaVMExt::IsWeakGlobalCleared(Thread* self, IndirectRef ref) {
913*795d594fSAndroid Build Coastguard Worker   DCHECK_EQ(IndirectReferenceTable::GetIndirectRefKind(ref), kWeakGlobal);
914*795d594fSAndroid Build Coastguard Worker   MutexLock mu(self, *Locks::jni_weak_globals_lock_);
915*795d594fSAndroid Build Coastguard Worker   WaitForWeakGlobalsAccess(self);
916*795d594fSAndroid Build Coastguard Worker   // When just checking a weak ref has been cleared, avoid triggering the read barrier in decode
917*795d594fSAndroid Build Coastguard Worker   // (DecodeWeakGlobal) so that we won't accidentally mark the object alive. Since the cleared
918*795d594fSAndroid Build Coastguard Worker   // sentinel is a non-moving object, we can compare the ref to it without the read barrier and
919*795d594fSAndroid Build Coastguard Worker   // decide if it's cleared.
920*795d594fSAndroid Build Coastguard Worker   return Runtime::Current()->IsClearedJniWeakGlobal(weak_globals_.Get<kWithoutReadBarrier>(ref));
921*795d594fSAndroid Build Coastguard Worker }
922*795d594fSAndroid Build Coastguard Worker 
UpdateWeakGlobal(Thread * self,IndirectRef ref,ObjPtr<mirror::Object> result)923*795d594fSAndroid Build Coastguard Worker void JavaVMExt::UpdateWeakGlobal(Thread* self, IndirectRef ref, ObjPtr<mirror::Object> result) {
924*795d594fSAndroid Build Coastguard Worker   MutexLock mu(self, *Locks::jni_weak_globals_lock_);
925*795d594fSAndroid Build Coastguard Worker   weak_globals_.Update(ref, result);
926*795d594fSAndroid Build Coastguard Worker }
927*795d594fSAndroid Build Coastguard Worker 
DumpReferenceTables(std::ostream & os)928*795d594fSAndroid Build Coastguard Worker void JavaVMExt::DumpReferenceTables(std::ostream& os) {
929*795d594fSAndroid Build Coastguard Worker   Thread* self = Thread::Current();
930*795d594fSAndroid Build Coastguard Worker   {
931*795d594fSAndroid Build Coastguard Worker     ReaderMutexLock mu(self, *Locks::jni_globals_lock_);
932*795d594fSAndroid Build Coastguard Worker     globals_.Dump(os);
933*795d594fSAndroid Build Coastguard Worker   }
934*795d594fSAndroid Build Coastguard Worker   {
935*795d594fSAndroid Build Coastguard Worker     MutexLock mu(self, *Locks::jni_weak_globals_lock_);
936*795d594fSAndroid Build Coastguard Worker     weak_globals_.Dump(os);
937*795d594fSAndroid Build Coastguard Worker   }
938*795d594fSAndroid Build Coastguard Worker }
939*795d594fSAndroid Build Coastguard Worker 
UnloadNativeLibraries()940*795d594fSAndroid Build Coastguard Worker void JavaVMExt::UnloadNativeLibraries() {
941*795d594fSAndroid Build Coastguard Worker   libraries_.get()->UnloadNativeLibraries();
942*795d594fSAndroid Build Coastguard Worker }
943*795d594fSAndroid Build Coastguard Worker 
UnloadBootNativeLibraries()944*795d594fSAndroid Build Coastguard Worker void JavaVMExt::UnloadBootNativeLibraries() {
945*795d594fSAndroid Build Coastguard Worker   libraries_.get()->UnloadBootNativeLibraries(this);
946*795d594fSAndroid Build Coastguard Worker }
947*795d594fSAndroid Build Coastguard Worker 
LoadNativeLibrary(JNIEnv * env,const std::string & path,jobject class_loader,jclass caller_class,std::string * error_msg)948*795d594fSAndroid Build Coastguard Worker bool JavaVMExt::LoadNativeLibrary(JNIEnv* env,
949*795d594fSAndroid Build Coastguard Worker                                   const std::string& path,
950*795d594fSAndroid Build Coastguard Worker                                   jobject class_loader,
951*795d594fSAndroid Build Coastguard Worker                                   jclass caller_class,
952*795d594fSAndroid Build Coastguard Worker                                   std::string* error_msg) {
953*795d594fSAndroid Build Coastguard Worker   error_msg->clear();
954*795d594fSAndroid Build Coastguard Worker 
955*795d594fSAndroid Build Coastguard Worker   // See if we've already loaded this library.  If we have, and the class loader
956*795d594fSAndroid Build Coastguard Worker   // matches, return successfully without doing anything.
957*795d594fSAndroid Build Coastguard Worker   // TODO: for better results we should canonicalize the pathname (or even compare
958*795d594fSAndroid Build Coastguard Worker   // inodes). This implementation is fine if everybody is using System.loadLibrary.
959*795d594fSAndroid Build Coastguard Worker   SharedLibrary* library;
960*795d594fSAndroid Build Coastguard Worker   Thread* self = Thread::Current();
961*795d594fSAndroid Build Coastguard Worker   {
962*795d594fSAndroid Build Coastguard Worker     // TODO: move the locking (and more of this logic) into Libraries.
963*795d594fSAndroid Build Coastguard Worker     MutexLock mu(self, *Locks::jni_libraries_lock_);
964*795d594fSAndroid Build Coastguard Worker     library = libraries_->Get(path);
965*795d594fSAndroid Build Coastguard Worker   }
966*795d594fSAndroid Build Coastguard Worker   void* class_loader_allocator = nullptr;
967*795d594fSAndroid Build Coastguard Worker   std::string caller_location;
968*795d594fSAndroid Build Coastguard Worker   {
969*795d594fSAndroid Build Coastguard Worker     ScopedObjectAccess soa(env);
970*795d594fSAndroid Build Coastguard Worker     // As the incoming class loader is reachable/alive during the call of this function,
971*795d594fSAndroid Build Coastguard Worker     // it's okay to decode it without worrying about unexpectedly marking it alive.
972*795d594fSAndroid Build Coastguard Worker     ObjPtr<mirror::ClassLoader> loader = soa.Decode<mirror::ClassLoader>(class_loader);
973*795d594fSAndroid Build Coastguard Worker 
974*795d594fSAndroid Build Coastguard Worker     ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
975*795d594fSAndroid Build Coastguard Worker     if (class_linker->IsBootClassLoader(loader)) {
976*795d594fSAndroid Build Coastguard Worker       loader = nullptr;
977*795d594fSAndroid Build Coastguard Worker       class_loader = nullptr;
978*795d594fSAndroid Build Coastguard Worker     }
979*795d594fSAndroid Build Coastguard Worker     if (caller_class != nullptr) {
980*795d594fSAndroid Build Coastguard Worker       ObjPtr<mirror::Class> caller = soa.Decode<mirror::Class>(caller_class);
981*795d594fSAndroid Build Coastguard Worker       ObjPtr<mirror::DexCache> dex_cache = caller->GetDexCache();
982*795d594fSAndroid Build Coastguard Worker       if (dex_cache != nullptr) {
983*795d594fSAndroid Build Coastguard Worker         caller_location = dex_cache->GetLocation()->ToModifiedUtf8();
984*795d594fSAndroid Build Coastguard Worker       }
985*795d594fSAndroid Build Coastguard Worker     }
986*795d594fSAndroid Build Coastguard Worker 
987*795d594fSAndroid Build Coastguard Worker     class_loader_allocator = class_linker->GetAllocatorForClassLoader(loader);
988*795d594fSAndroid Build Coastguard Worker     CHECK(class_loader_allocator != nullptr);
989*795d594fSAndroid Build Coastguard Worker   }
990*795d594fSAndroid Build Coastguard Worker   if (library != nullptr) {
991*795d594fSAndroid Build Coastguard Worker     // Use the allocator pointers for class loader equality to avoid unnecessary weak root decode.
992*795d594fSAndroid Build Coastguard Worker     if (library->GetClassLoaderAllocator() != class_loader_allocator) {
993*795d594fSAndroid Build Coastguard Worker       // The library will be associated with class_loader. The JNI
994*795d594fSAndroid Build Coastguard Worker       // spec says we can't load the same library into more than one
995*795d594fSAndroid Build Coastguard Worker       // class loader.
996*795d594fSAndroid Build Coastguard Worker       //
997*795d594fSAndroid Build Coastguard Worker       // This isn't very common. So spend some time to get a readable message.
998*795d594fSAndroid Build Coastguard Worker       auto call_to_string = [&](jobject obj) -> std::string {
999*795d594fSAndroid Build Coastguard Worker         if (obj == nullptr) {
1000*795d594fSAndroid Build Coastguard Worker           return "null";
1001*795d594fSAndroid Build Coastguard Worker         }
1002*795d594fSAndroid Build Coastguard Worker         // Handle jweaks. Ignore double local-ref.
1003*795d594fSAndroid Build Coastguard Worker         ScopedLocalRef<jobject> local_ref(env, env->NewLocalRef(obj));
1004*795d594fSAndroid Build Coastguard Worker         if (local_ref != nullptr) {
1005*795d594fSAndroid Build Coastguard Worker           ScopedLocalRef<jclass> local_class(env, env->GetObjectClass(local_ref.get()));
1006*795d594fSAndroid Build Coastguard Worker           jmethodID to_string = env->GetMethodID(local_class.get(),
1007*795d594fSAndroid Build Coastguard Worker                                                  "toString",
1008*795d594fSAndroid Build Coastguard Worker                                                  "()Ljava/lang/String;");
1009*795d594fSAndroid Build Coastguard Worker           DCHECK(to_string != nullptr);
1010*795d594fSAndroid Build Coastguard Worker           ScopedLocalRef<jobject> local_string(env,
1011*795d594fSAndroid Build Coastguard Worker                                                env->CallObjectMethod(local_ref.get(), to_string));
1012*795d594fSAndroid Build Coastguard Worker           if (local_string != nullptr) {
1013*795d594fSAndroid Build Coastguard Worker             ScopedUtfChars utf(env, reinterpret_cast<jstring>(local_string.get()));
1014*795d594fSAndroid Build Coastguard Worker             if (utf.c_str() != nullptr) {
1015*795d594fSAndroid Build Coastguard Worker               return utf.c_str();
1016*795d594fSAndroid Build Coastguard Worker             }
1017*795d594fSAndroid Build Coastguard Worker           }
1018*795d594fSAndroid Build Coastguard Worker           if (env->ExceptionCheck()) {
1019*795d594fSAndroid Build Coastguard Worker             // We can't do much better logging, really. So leave it with a Describe.
1020*795d594fSAndroid Build Coastguard Worker             env->ExceptionDescribe();
1021*795d594fSAndroid Build Coastguard Worker             env->ExceptionClear();
1022*795d594fSAndroid Build Coastguard Worker           }
1023*795d594fSAndroid Build Coastguard Worker           return "(Error calling toString)";
1024*795d594fSAndroid Build Coastguard Worker         }
1025*795d594fSAndroid Build Coastguard Worker         return "null";
1026*795d594fSAndroid Build Coastguard Worker       };
1027*795d594fSAndroid Build Coastguard Worker       std::string old_class_loader = call_to_string(library->GetClassLoader());
1028*795d594fSAndroid Build Coastguard Worker       std::string new_class_loader = call_to_string(class_loader);
1029*795d594fSAndroid Build Coastguard Worker       StringAppendF(error_msg, "Shared library \"%s\" already opened by "
1030*795d594fSAndroid Build Coastguard Worker           "ClassLoader %p(%s); can't open in ClassLoader %p(%s)",
1031*795d594fSAndroid Build Coastguard Worker           path.c_str(),
1032*795d594fSAndroid Build Coastguard Worker           library->GetClassLoader(),
1033*795d594fSAndroid Build Coastguard Worker           old_class_loader.c_str(),
1034*795d594fSAndroid Build Coastguard Worker           class_loader,
1035*795d594fSAndroid Build Coastguard Worker           new_class_loader.c_str());
1036*795d594fSAndroid Build Coastguard Worker       LOG(WARNING) << *error_msg;
1037*795d594fSAndroid Build Coastguard Worker       return false;
1038*795d594fSAndroid Build Coastguard Worker     }
1039*795d594fSAndroid Build Coastguard Worker     VLOG(jni) << "[Shared library \"" << path << "\" already loaded in "
1040*795d594fSAndroid Build Coastguard Worker               << " ClassLoader " << class_loader << "]";
1041*795d594fSAndroid Build Coastguard Worker     if (!library->CheckOnLoadResult()) {
1042*795d594fSAndroid Build Coastguard Worker       StringAppendF(error_msg, "JNI_OnLoad failed on a previous attempt "
1043*795d594fSAndroid Build Coastguard Worker           "to load \"%s\"", path.c_str());
1044*795d594fSAndroid Build Coastguard Worker       return false;
1045*795d594fSAndroid Build Coastguard Worker     }
1046*795d594fSAndroid Build Coastguard Worker     return true;
1047*795d594fSAndroid Build Coastguard Worker   }
1048*795d594fSAndroid Build Coastguard Worker 
1049*795d594fSAndroid Build Coastguard Worker   // Open the shared library.  Because we're using a full path, the system
1050*795d594fSAndroid Build Coastguard Worker   // doesn't have to search through LD_LIBRARY_PATH.  (It may do so to
1051*795d594fSAndroid Build Coastguard Worker   // resolve this library's dependencies though.)
1052*795d594fSAndroid Build Coastguard Worker 
1053*795d594fSAndroid Build Coastguard Worker   // Failures here are expected when java.library.path has several entries
1054*795d594fSAndroid Build Coastguard Worker   // and we have to hunt for the lib.
1055*795d594fSAndroid Build Coastguard Worker 
1056*795d594fSAndroid Build Coastguard Worker   // Below we dlopen but there is no paired dlclose, this would be necessary if we supported
1057*795d594fSAndroid Build Coastguard Worker   // class unloading. Libraries will only be unloaded when the reference count (incremented by
1058*795d594fSAndroid Build Coastguard Worker   // dlopen) becomes zero from dlclose.
1059*795d594fSAndroid Build Coastguard Worker 
1060*795d594fSAndroid Build Coastguard Worker   // Retrieve the library path from the classloader, if necessary.
1061*795d594fSAndroid Build Coastguard Worker   ScopedLocalRef<jstring> library_path(env, GetLibrarySearchPath(env, class_loader));
1062*795d594fSAndroid Build Coastguard Worker 
1063*795d594fSAndroid Build Coastguard Worker   Locks::mutator_lock_->AssertNotHeld(self);
1064*795d594fSAndroid Build Coastguard Worker   const char* path_str = path.empty() ? nullptr : path.c_str();
1065*795d594fSAndroid Build Coastguard Worker   bool needs_native_bridge = false;
1066*795d594fSAndroid Build Coastguard Worker   char* nativeloader_error_msg = nullptr;
1067*795d594fSAndroid Build Coastguard Worker   void* handle = android::OpenNativeLibrary(
1068*795d594fSAndroid Build Coastguard Worker       env,
1069*795d594fSAndroid Build Coastguard Worker       runtime_->GetTargetSdkVersion(),
1070*795d594fSAndroid Build Coastguard Worker       path_str,
1071*795d594fSAndroid Build Coastguard Worker       class_loader,
1072*795d594fSAndroid Build Coastguard Worker       (caller_location.empty() ? nullptr : caller_location.c_str()),
1073*795d594fSAndroid Build Coastguard Worker       library_path.get(),
1074*795d594fSAndroid Build Coastguard Worker       &needs_native_bridge,
1075*795d594fSAndroid Build Coastguard Worker       &nativeloader_error_msg);
1076*795d594fSAndroid Build Coastguard Worker   VLOG(jni) << "[Call to dlopen(\"" << path << "\", RTLD_NOW) returned " << handle << "]";
1077*795d594fSAndroid Build Coastguard Worker 
1078*795d594fSAndroid Build Coastguard Worker   if (handle == nullptr) {
1079*795d594fSAndroid Build Coastguard Worker     *error_msg = nativeloader_error_msg;
1080*795d594fSAndroid Build Coastguard Worker     android::NativeLoaderFreeErrorMessage(nativeloader_error_msg);
1081*795d594fSAndroid Build Coastguard Worker     VLOG(jni) << "dlopen(\"" << path << "\", RTLD_NOW) failed: " << *error_msg;
1082*795d594fSAndroid Build Coastguard Worker     return false;
1083*795d594fSAndroid Build Coastguard Worker   }
1084*795d594fSAndroid Build Coastguard Worker 
1085*795d594fSAndroid Build Coastguard Worker   if (env->ExceptionCheck() == JNI_TRUE) {
1086*795d594fSAndroid Build Coastguard Worker     LOG(ERROR) << "Unexpected exception:";
1087*795d594fSAndroid Build Coastguard Worker     env->ExceptionDescribe();
1088*795d594fSAndroid Build Coastguard Worker     env->ExceptionClear();
1089*795d594fSAndroid Build Coastguard Worker   }
1090*795d594fSAndroid Build Coastguard Worker   // Create a new entry.
1091*795d594fSAndroid Build Coastguard Worker   // TODO: move the locking (and more of this logic) into Libraries.
1092*795d594fSAndroid Build Coastguard Worker   bool created_library = false;
1093*795d594fSAndroid Build Coastguard Worker   {
1094*795d594fSAndroid Build Coastguard Worker     // Create SharedLibrary ahead of taking the libraries lock to maintain lock ordering.
1095*795d594fSAndroid Build Coastguard Worker     std::unique_ptr<SharedLibrary> new_library(
1096*795d594fSAndroid Build Coastguard Worker         new SharedLibrary(env,
1097*795d594fSAndroid Build Coastguard Worker                           self,
1098*795d594fSAndroid Build Coastguard Worker                           path,
1099*795d594fSAndroid Build Coastguard Worker                           handle,
1100*795d594fSAndroid Build Coastguard Worker                           needs_native_bridge,
1101*795d594fSAndroid Build Coastguard Worker                           class_loader,
1102*795d594fSAndroid Build Coastguard Worker                           class_loader_allocator));
1103*795d594fSAndroid Build Coastguard Worker 
1104*795d594fSAndroid Build Coastguard Worker     MutexLock mu(self, *Locks::jni_libraries_lock_);
1105*795d594fSAndroid Build Coastguard Worker     library = libraries_->Get(path);
1106*795d594fSAndroid Build Coastguard Worker     if (library == nullptr) {  // We won race to get libraries_lock.
1107*795d594fSAndroid Build Coastguard Worker       library = new_library.release();
1108*795d594fSAndroid Build Coastguard Worker       libraries_->Put(path, library);
1109*795d594fSAndroid Build Coastguard Worker       created_library = true;
1110*795d594fSAndroid Build Coastguard Worker     }
1111*795d594fSAndroid Build Coastguard Worker   }
1112*795d594fSAndroid Build Coastguard Worker   if (!created_library) {
1113*795d594fSAndroid Build Coastguard Worker     LOG(INFO) << "WOW: we lost a race to add shared library: "
1114*795d594fSAndroid Build Coastguard Worker         << "\"" << path << "\" ClassLoader=" << class_loader;
1115*795d594fSAndroid Build Coastguard Worker     return library->CheckOnLoadResult();
1116*795d594fSAndroid Build Coastguard Worker   }
1117*795d594fSAndroid Build Coastguard Worker   VLOG(jni) << "[Added shared library \"" << path << "\" for ClassLoader " << class_loader << "]";
1118*795d594fSAndroid Build Coastguard Worker 
1119*795d594fSAndroid Build Coastguard Worker   bool was_successful = false;
1120*795d594fSAndroid Build Coastguard Worker   void* sym = library->FindSymbol("JNI_OnLoad", nullptr, android::kJNICallTypeRegular);
1121*795d594fSAndroid Build Coastguard Worker   if (sym == nullptr) {
1122*795d594fSAndroid Build Coastguard Worker     VLOG(jni) << "[No JNI_OnLoad found in \"" << path << "\"]";
1123*795d594fSAndroid Build Coastguard Worker     was_successful = true;
1124*795d594fSAndroid Build Coastguard Worker   } else {
1125*795d594fSAndroid Build Coastguard Worker     // Call JNI_OnLoad.  We have to override the current class
1126*795d594fSAndroid Build Coastguard Worker     // loader, which will always be "null" since the stuff at the
1127*795d594fSAndroid Build Coastguard Worker     // top of the stack is around Runtime.loadLibrary().  (See
1128*795d594fSAndroid Build Coastguard Worker     // the comments in the JNI FindClass function.)
1129*795d594fSAndroid Build Coastguard Worker     ScopedLocalRef<jobject> old_class_loader(env, env->NewLocalRef(self->GetClassLoaderOverride()));
1130*795d594fSAndroid Build Coastguard Worker     self->SetClassLoaderOverride(class_loader);
1131*795d594fSAndroid Build Coastguard Worker 
1132*795d594fSAndroid Build Coastguard Worker     VLOG(jni) << "[Calling JNI_OnLoad in \"" << path << "\"]";
1133*795d594fSAndroid Build Coastguard Worker     using JNI_OnLoadFn = int(*)(JavaVM*, void*);
1134*795d594fSAndroid Build Coastguard Worker     JNI_OnLoadFn jni_on_load = reinterpret_cast<JNI_OnLoadFn>(sym);
1135*795d594fSAndroid Build Coastguard Worker     int version = (*jni_on_load)(this, nullptr);
1136*795d594fSAndroid Build Coastguard Worker 
1137*795d594fSAndroid Build Coastguard Worker     if (IsSdkVersionSetAndAtMost(runtime_->GetTargetSdkVersion(), SdkVersion::kL)) {
1138*795d594fSAndroid Build Coastguard Worker       // Make sure that sigchain owns SIGSEGV.
1139*795d594fSAndroid Build Coastguard Worker       EnsureFrontOfChain(SIGSEGV);
1140*795d594fSAndroid Build Coastguard Worker     }
1141*795d594fSAndroid Build Coastguard Worker 
1142*795d594fSAndroid Build Coastguard Worker     self->SetClassLoaderOverride(old_class_loader.get());
1143*795d594fSAndroid Build Coastguard Worker 
1144*795d594fSAndroid Build Coastguard Worker     if (version == JNI_ERR) {
1145*795d594fSAndroid Build Coastguard Worker       StringAppendF(error_msg, "JNI_ERR returned from JNI_OnLoad in \"%s\"", path.c_str());
1146*795d594fSAndroid Build Coastguard Worker     } else if (JavaVMExt::IsBadJniVersion(version)) {
1147*795d594fSAndroid Build Coastguard Worker       StringAppendF(error_msg, "Bad JNI version returned from JNI_OnLoad in \"%s\": %d",
1148*795d594fSAndroid Build Coastguard Worker                     path.c_str(), version);
1149*795d594fSAndroid Build Coastguard Worker       // It's unwise to call dlclose() here, but we can mark it
1150*795d594fSAndroid Build Coastguard Worker       // as bad and ensure that future load attempts will fail.
1151*795d594fSAndroid Build Coastguard Worker       // We don't know how far JNI_OnLoad got, so there could
1152*795d594fSAndroid Build Coastguard Worker       // be some partially-initialized stuff accessible through
1153*795d594fSAndroid Build Coastguard Worker       // newly-registered native method calls.  We could try to
1154*795d594fSAndroid Build Coastguard Worker       // unregister them, but that doesn't seem worthwhile.
1155*795d594fSAndroid Build Coastguard Worker     } else {
1156*795d594fSAndroid Build Coastguard Worker       was_successful = true;
1157*795d594fSAndroid Build Coastguard Worker     }
1158*795d594fSAndroid Build Coastguard Worker     VLOG(jni) << "[Returned " << (was_successful ? "successfully" : "failure")
1159*795d594fSAndroid Build Coastguard Worker               << " from JNI_OnLoad in \"" << path << "\"]";
1160*795d594fSAndroid Build Coastguard Worker   }
1161*795d594fSAndroid Build Coastguard Worker 
1162*795d594fSAndroid Build Coastguard Worker   library->SetResult(was_successful);
1163*795d594fSAndroid Build Coastguard Worker   return was_successful;
1164*795d594fSAndroid Build Coastguard Worker }
1165*795d594fSAndroid Build Coastguard Worker 
FindCodeForNativeMethodInAgents(ArtMethod * m)1166*795d594fSAndroid Build Coastguard Worker static void* FindCodeForNativeMethodInAgents(ArtMethod* m) REQUIRES_SHARED(Locks::mutator_lock_) {
1167*795d594fSAndroid Build Coastguard Worker   std::string jni_short_name(m->JniShortName());
1168*795d594fSAndroid Build Coastguard Worker   std::string jni_long_name(m->JniLongName());
1169*795d594fSAndroid Build Coastguard Worker   for (const std::unique_ptr<ti::Agent>& agent : Runtime::Current()->GetAgents()) {
1170*795d594fSAndroid Build Coastguard Worker     void* fn = agent->FindSymbol(jni_short_name);
1171*795d594fSAndroid Build Coastguard Worker     if (fn != nullptr) {
1172*795d594fSAndroid Build Coastguard Worker       VLOG(jni) << "Found implementation for " << m->PrettyMethod()
1173*795d594fSAndroid Build Coastguard Worker                 << " (symbol: " << jni_short_name << ") in " << *agent;
1174*795d594fSAndroid Build Coastguard Worker       return fn;
1175*795d594fSAndroid Build Coastguard Worker     }
1176*795d594fSAndroid Build Coastguard Worker     fn = agent->FindSymbol(jni_long_name);
1177*795d594fSAndroid Build Coastguard Worker     if (fn != nullptr) {
1178*795d594fSAndroid Build Coastguard Worker       VLOG(jni) << "Found implementation for " << m->PrettyMethod()
1179*795d594fSAndroid Build Coastguard Worker                 << " (symbol: " << jni_long_name << ") in " << *agent;
1180*795d594fSAndroid Build Coastguard Worker       return fn;
1181*795d594fSAndroid Build Coastguard Worker     }
1182*795d594fSAndroid Build Coastguard Worker   }
1183*795d594fSAndroid Build Coastguard Worker   return nullptr;
1184*795d594fSAndroid Build Coastguard Worker }
1185*795d594fSAndroid Build Coastguard Worker 
FindCodeForNativeMethod(ArtMethod * m,std::string * error_msg,bool can_suspend)1186*795d594fSAndroid Build Coastguard Worker void* JavaVMExt::FindCodeForNativeMethod(ArtMethod* m, std::string* error_msg, bool can_suspend) {
1187*795d594fSAndroid Build Coastguard Worker   CHECK(m->IsNative());
1188*795d594fSAndroid Build Coastguard Worker   ObjPtr<mirror::Class> c = m->GetDeclaringClass();
1189*795d594fSAndroid Build Coastguard Worker   // If this is a static method, it could be called before the class has been initialized.
1190*795d594fSAndroid Build Coastguard Worker   CHECK(c->IsInitializing() || !m->NeedsClinitCheckBeforeCall())
1191*795d594fSAndroid Build Coastguard Worker       << c->GetStatus() << " " << m->PrettyMethod();
1192*795d594fSAndroid Build Coastguard Worker   Thread* const self = Thread::Current();
1193*795d594fSAndroid Build Coastguard Worker   void* native_method = libraries_->FindNativeMethod(self, m, error_msg, can_suspend);
1194*795d594fSAndroid Build Coastguard Worker   if (native_method == nullptr && can_suspend) {
1195*795d594fSAndroid Build Coastguard Worker     // Lookup JNI native methods from native TI Agent libraries. See runtime/ti/agent.h for more
1196*795d594fSAndroid Build Coastguard Worker     // information. Agent libraries are searched for native methods after all jni libraries.
1197*795d594fSAndroid Build Coastguard Worker     native_method = FindCodeForNativeMethodInAgents(m);
1198*795d594fSAndroid Build Coastguard Worker   }
1199*795d594fSAndroid Build Coastguard Worker   return native_method;
1200*795d594fSAndroid Build Coastguard Worker }
1201*795d594fSAndroid Build Coastguard Worker 
TrimGlobals()1202*795d594fSAndroid Build Coastguard Worker void JavaVMExt::TrimGlobals() {
1203*795d594fSAndroid Build Coastguard Worker   WriterMutexLock mu(Thread::Current(), *Locks::jni_globals_lock_);
1204*795d594fSAndroid Build Coastguard Worker   globals_.Trim();
1205*795d594fSAndroid Build Coastguard Worker }
1206*795d594fSAndroid Build Coastguard Worker 
VisitRoots(RootVisitor * visitor)1207*795d594fSAndroid Build Coastguard Worker void JavaVMExt::VisitRoots(RootVisitor* visitor) {
1208*795d594fSAndroid Build Coastguard Worker   Thread* self = Thread::Current();
1209*795d594fSAndroid Build Coastguard Worker   ReaderMutexLock mu(self, *Locks::jni_globals_lock_);
1210*795d594fSAndroid Build Coastguard Worker   globals_.VisitRoots(visitor, RootInfo(kRootJNIGlobal));
1211*795d594fSAndroid Build Coastguard Worker   // The weak_globals table is visited by the GC itself (because it mutates the table).
1212*795d594fSAndroid Build Coastguard Worker }
1213*795d594fSAndroid Build Coastguard Worker 
GetLibrarySearchPath(JNIEnv * env,jobject class_loader)1214*795d594fSAndroid Build Coastguard Worker jstring JavaVMExt::GetLibrarySearchPath(JNIEnv* env, jobject class_loader) {
1215*795d594fSAndroid Build Coastguard Worker   if (class_loader == nullptr) {
1216*795d594fSAndroid Build Coastguard Worker     return nullptr;
1217*795d594fSAndroid Build Coastguard Worker   }
1218*795d594fSAndroid Build Coastguard Worker   ScopedObjectAccess soa(env);
1219*795d594fSAndroid Build Coastguard Worker   ObjPtr<mirror::Object> mirror_class_loader = soa.Decode<mirror::Object>(class_loader);
1220*795d594fSAndroid Build Coastguard Worker   if (!mirror_class_loader->InstanceOf(WellKnownClasses::dalvik_system_BaseDexClassLoader.Get())) {
1221*795d594fSAndroid Build Coastguard Worker     return nullptr;
1222*795d594fSAndroid Build Coastguard Worker   }
1223*795d594fSAndroid Build Coastguard Worker   return soa.AddLocalReference<jstring>(
1224*795d594fSAndroid Build Coastguard Worker       WellKnownClasses::dalvik_system_BaseDexClassLoader_getLdLibraryPath->InvokeVirtual<'L'>(
1225*795d594fSAndroid Build Coastguard Worker           soa.Self(), mirror_class_loader));
1226*795d594fSAndroid Build Coastguard Worker }
1227*795d594fSAndroid Build Coastguard Worker 
1228*795d594fSAndroid Build Coastguard Worker // JNI Invocation interface.
1229*795d594fSAndroid Build Coastguard Worker 
JNI_CreateJavaVM(JavaVM ** p_vm,JNIEnv ** p_env,void * vm_args)1230*795d594fSAndroid Build Coastguard Worker extern "C" EXPORT jint JNI_CreateJavaVM(JavaVM** p_vm, JNIEnv** p_env, void* vm_args) {
1231*795d594fSAndroid Build Coastguard Worker   ScopedTrace trace(__FUNCTION__);
1232*795d594fSAndroid Build Coastguard Worker   const JavaVMInitArgs* args = static_cast<JavaVMInitArgs*>(vm_args);
1233*795d594fSAndroid Build Coastguard Worker   if (JavaVMExt::IsBadJniVersion(args->version)) {
1234*795d594fSAndroid Build Coastguard Worker     LOG(ERROR) << "Bad JNI version passed to CreateJavaVM: " << args->version;
1235*795d594fSAndroid Build Coastguard Worker     return JNI_EVERSION;
1236*795d594fSAndroid Build Coastguard Worker   }
1237*795d594fSAndroid Build Coastguard Worker   RuntimeOptions options;
1238*795d594fSAndroid Build Coastguard Worker   for (int i = 0; i < args->nOptions; ++i) {
1239*795d594fSAndroid Build Coastguard Worker     JavaVMOption* option = &args->options[i];
1240*795d594fSAndroid Build Coastguard Worker     options.push_back(std::make_pair(std::string(option->optionString), option->extraInfo));
1241*795d594fSAndroid Build Coastguard Worker   }
1242*795d594fSAndroid Build Coastguard Worker   bool ignore_unrecognized = args->ignoreUnrecognized;
1243*795d594fSAndroid Build Coastguard Worker   if (!Runtime::Create(options, ignore_unrecognized)) {
1244*795d594fSAndroid Build Coastguard Worker     return JNI_ERR;
1245*795d594fSAndroid Build Coastguard Worker   }
1246*795d594fSAndroid Build Coastguard Worker 
1247*795d594fSAndroid Build Coastguard Worker   // When `ART_CRASH_RUNTIME_DELIBERATELY` is defined (which happens only in the
1248*795d594fSAndroid Build Coastguard Worker   // case of a test APEX), we crash the runtime here on purpose, to test the
1249*795d594fSAndroid Build Coastguard Worker   // behavior of rollbacks following a failed ART Mainline Module update.
1250*795d594fSAndroid Build Coastguard Worker #ifdef ART_CRASH_RUNTIME_DELIBERATELY
1251*795d594fSAndroid Build Coastguard Worker   LOG(FATAL) << "Runtime crashing deliberately for testing purposes.";
1252*795d594fSAndroid Build Coastguard Worker #endif
1253*795d594fSAndroid Build Coastguard Worker 
1254*795d594fSAndroid Build Coastguard Worker   // Initialize native loader. This step makes sure we have
1255*795d594fSAndroid Build Coastguard Worker   // everything set up before we start using JNI.
1256*795d594fSAndroid Build Coastguard Worker   android::InitializeNativeLoader();
1257*795d594fSAndroid Build Coastguard Worker 
1258*795d594fSAndroid Build Coastguard Worker   Runtime* runtime = Runtime::Current();
1259*795d594fSAndroid Build Coastguard Worker   bool started = runtime->Start();
1260*795d594fSAndroid Build Coastguard Worker   if (!started) {
1261*795d594fSAndroid Build Coastguard Worker     delete Thread::Current()->GetJniEnv();
1262*795d594fSAndroid Build Coastguard Worker     delete runtime->GetJavaVM();
1263*795d594fSAndroid Build Coastguard Worker     LOG(WARNING) << "CreateJavaVM failed";
1264*795d594fSAndroid Build Coastguard Worker     return JNI_ERR;
1265*795d594fSAndroid Build Coastguard Worker   }
1266*795d594fSAndroid Build Coastguard Worker 
1267*795d594fSAndroid Build Coastguard Worker   *p_env = Thread::Current()->GetJniEnv();
1268*795d594fSAndroid Build Coastguard Worker   *p_vm = runtime->GetJavaVM();
1269*795d594fSAndroid Build Coastguard Worker   return JNI_OK;
1270*795d594fSAndroid Build Coastguard Worker }
1271*795d594fSAndroid Build Coastguard Worker 
JNI_GetCreatedJavaVMs(JavaVM ** vms_buf,jsize buf_len,jsize * vm_count)1272*795d594fSAndroid Build Coastguard Worker extern "C" EXPORT jint JNI_GetCreatedJavaVMs(JavaVM** vms_buf, jsize buf_len, jsize* vm_count) {
1273*795d594fSAndroid Build Coastguard Worker   Runtime* runtime = Runtime::Current();
1274*795d594fSAndroid Build Coastguard Worker   if (runtime == nullptr || buf_len == 0) {
1275*795d594fSAndroid Build Coastguard Worker     *vm_count = 0;
1276*795d594fSAndroid Build Coastguard Worker   } else {
1277*795d594fSAndroid Build Coastguard Worker     *vm_count = 1;
1278*795d594fSAndroid Build Coastguard Worker     vms_buf[0] = runtime->GetJavaVM();
1279*795d594fSAndroid Build Coastguard Worker   }
1280*795d594fSAndroid Build Coastguard Worker   return JNI_OK;
1281*795d594fSAndroid Build Coastguard Worker }
1282*795d594fSAndroid Build Coastguard Worker 
1283*795d594fSAndroid Build Coastguard Worker // Historically unsupported.
JNI_GetDefaultJavaVMInitArgs(void *)1284*795d594fSAndroid Build Coastguard Worker extern "C" EXPORT jint JNI_GetDefaultJavaVMInitArgs(void* /*vm_args*/) {
1285*795d594fSAndroid Build Coastguard Worker   return JNI_ERR;
1286*795d594fSAndroid Build Coastguard Worker }
1287*795d594fSAndroid Build Coastguard Worker 
1288*795d594fSAndroid Build Coastguard Worker }  // namespace art
1289