• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2011 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef ART_RUNTIME_JNI_JAVA_VM_EXT_H_
18 #define ART_RUNTIME_JNI_JAVA_VM_EXT_H_
19 
20 #include "jni.h"
21 
22 #include "base/macros.h"
23 #include "base/mutex.h"
24 #include "indirect_reference_table.h"
25 #include "obj_ptr.h"
26 #include "reference_table.h"
27 
28 namespace art {
29 
30 namespace linker {
31 class ImageWriter;
32 }  // namespace linker
33 
34 namespace mirror {
35 class Array;
36 }  // namespace mirror
37 
38 class ArtMethod;
39 class IsMarkedVisitor;
40 class Libraries;
41 class ParsedOptions;
42 class Runtime;
43 struct RuntimeArgumentMap;
44 class ScopedObjectAccess;
45 
46 class JavaVMExt;
47 // Hook definition for runtime plugins.
48 using GetEnvHook = jint (*)(JavaVMExt* vm, /*out*/void** new_env, jint version);
49 
50 class JavaVMExt : public JavaVM {
51  public:
52   // Creates a new JavaVMExt object.
53   // Returns nullptr on error, in which case error_msg is set to a message
54   // describing the error.
55   static std::unique_ptr<JavaVMExt> Create(Runtime* runtime,
56                                            const RuntimeArgumentMap& runtime_options,
57                                            std::string* error_msg);
58 
59 
60   ~JavaVMExt();
61 
ForceCopy()62   bool ForceCopy() const {
63     return force_copy_;
64   }
65 
IsCheckJniEnabled()66   bool IsCheckJniEnabled() const {
67     return check_jni_;
68   }
69 
IsTracingEnabled()70   bool IsTracingEnabled() const {
71     return tracing_enabled_;
72   }
73 
GetRuntime()74   Runtime* GetRuntime() const {
75     return runtime_;
76   }
77 
SetCheckJniAbortHook(void (* hook)(void *,const std::string &),void * data)78   void SetCheckJniAbortHook(void (*hook)(void*, const std::string&), void* data) {
79     check_jni_abort_hook_ = hook;
80     check_jni_abort_hook_data_ = data;
81   }
82 
83   // Aborts execution unless there is an abort handler installed in which case it will return. Its
84   // therefore important that callers return after aborting as otherwise code following the abort
85   // will be executed in the abort handler case.
86   void JniAbort(const char* jni_function_name, const char* msg);
87 
88   void JniAbortV(const char* jni_function_name, const char* fmt, va_list ap);
89 
90   void JniAbortF(const char* jni_function_name, const char* fmt, ...)
91       __attribute__((__format__(__printf__, 3, 4)));
92 
93   // If both "-Xcheck:jni" and "-Xjnitrace:" are enabled, we print trace messages
94   // when a native method that matches the -Xjnitrace argument calls a JNI function
95   // such as NewByteArray.
96   // If -verbose:third-party-jni is on, we want to log any JNI function calls
97   // made by a third-party native method.
98   bool ShouldTrace(ArtMethod* method) REQUIRES_SHARED(Locks::mutator_lock_);
99 
100   /**
101    * Loads the given shared library. 'path' is an absolute pathname.
102    *
103    * Returns 'true' on success. On failure, sets 'error_msg' to a
104    * human-readable description of the error.
105    */
106   bool LoadNativeLibrary(JNIEnv* env,
107                          const std::string& path,
108                          jobject class_loader,
109                          jclass caller_class,
110                          std::string* error_msg);
111 
112   // Unload native libraries with cleared class loaders.
113   void UnloadNativeLibraries()
114       REQUIRES(!Locks::jni_libraries_lock_)
115       REQUIRES_SHARED(Locks::mutator_lock_);
116 
117   // Unload all boot classpath native libraries.
118   void UnloadBootNativeLibraries()
119       REQUIRES(!Locks::jni_libraries_lock_)
120       REQUIRES_SHARED(Locks::mutator_lock_);
121 
122   /**
123    * Returns a pointer to the code for the native method 'm', found
124    * using dlsym(3) on every native library that's been loaded so far.
125    */
126   void* FindCodeForNativeMethod(ArtMethod* m, std::string* error_msg, bool can_suspend)
127       REQUIRES_SHARED(Locks::mutator_lock_);
128 
129   void DumpForSigQuit(std::ostream& os)
130       REQUIRES(!Locks::jni_libraries_lock_,
131                !Locks::jni_globals_lock_,
132                !Locks::jni_weak_globals_lock_);
133 
134   void DumpReferenceTables(std::ostream& os)
135       REQUIRES_SHARED(Locks::mutator_lock_)
136       REQUIRES(!Locks::jni_globals_lock_,
137                !Locks::jni_weak_globals_lock_,
138                !Locks::alloc_tracker_lock_);
139 
140   bool SetCheckJniEnabled(bool enabled);
141 
142   void VisitRoots(RootVisitor* visitor) REQUIRES_SHARED(Locks::mutator_lock_)
143       REQUIRES(!Locks::jni_globals_lock_);
144 
145   void DisallowNewWeakGlobals()
146       REQUIRES_SHARED(Locks::mutator_lock_)
147       REQUIRES(!Locks::jni_weak_globals_lock_);
148   void AllowNewWeakGlobals()
149       REQUIRES_SHARED(Locks::mutator_lock_)
150       REQUIRES(!Locks::jni_weak_globals_lock_);
151   void BroadcastForNewWeakGlobals()
152       REQUIRES(!Locks::jni_weak_globals_lock_);
153 
154   jobject AddGlobalRef(Thread* self, ObjPtr<mirror::Object> obj)
155       REQUIRES_SHARED(Locks::mutator_lock_)
156       REQUIRES(!Locks::jni_globals_lock_);
157 
158   jweak AddWeakGlobalRef(Thread* self, ObjPtr<mirror::Object> obj)
159       REQUIRES_SHARED(Locks::mutator_lock_)
160       REQUIRES(!Locks::jni_weak_globals_lock_);
161 
162   void DeleteGlobalRef(Thread* self, jobject obj) REQUIRES(!Locks::jni_globals_lock_);
163 
164   void DeleteWeakGlobalRef(Thread* self, jweak obj) REQUIRES(!Locks::jni_weak_globals_lock_);
165 
SweepJniWeakGlobals(IsMarkedVisitor * visitor)166   void SweepJniWeakGlobals(IsMarkedVisitor* visitor)
167       REQUIRES_SHARED(Locks::mutator_lock_)
168       REQUIRES(!Locks::jni_weak_globals_lock_) {
169     weak_globals_.SweepJniWeakGlobals(visitor);
170   }
171 
172   ObjPtr<mirror::Object> DecodeGlobal(IndirectRef ref)
173       REQUIRES_SHARED(Locks::mutator_lock_);
174 
175   void UpdateGlobal(Thread* self, IndirectRef ref, ObjPtr<mirror::Object> result)
176       REQUIRES_SHARED(Locks::mutator_lock_)
177       REQUIRES(!Locks::jni_globals_lock_);
178 
179   ObjPtr<mirror::Object> DecodeWeakGlobal(Thread* self, IndirectRef ref)
180       REQUIRES_SHARED(Locks::mutator_lock_)
181       REQUIRES(!Locks::jni_weak_globals_lock_);
182 
183   ObjPtr<mirror::Object> DecodeWeakGlobalLocked(Thread* self, IndirectRef ref)
184       REQUIRES_SHARED(Locks::mutator_lock_)
185       REQUIRES(Locks::jni_weak_globals_lock_);
186 
187   // Decode weak global as strong. Use only if the target object is known to be alive.
188   ObjPtr<mirror::Object> DecodeWeakGlobalAsStrong(IndirectRef ref)
189       REQUIRES_SHARED(Locks::mutator_lock_)
190       REQUIRES(!Locks::jni_weak_globals_lock_);
191 
192   // Like DecodeWeakGlobal() but to be used only during a runtime shutdown where self may be
193   // null.
194   ObjPtr<mirror::Object> DecodeWeakGlobalDuringShutdown(Thread* self, IndirectRef ref)
195       REQUIRES_SHARED(Locks::mutator_lock_)
196       REQUIRES(!Locks::jni_weak_globals_lock_);
197 
198   // Checks if the weak global ref has been cleared by the GC without decode (read barrier.)
199   bool IsWeakGlobalCleared(Thread* self, IndirectRef ref)
200       REQUIRES_SHARED(Locks::mutator_lock_)
201       REQUIRES(!Locks::jni_weak_globals_lock_);
202 
203   void UpdateWeakGlobal(Thread* self, IndirectRef ref, ObjPtr<mirror::Object> result)
204       REQUIRES_SHARED(Locks::mutator_lock_)
205       REQUIRES(!Locks::jni_weak_globals_lock_);
206 
GetUncheckedFunctions()207   const JNIInvokeInterface* GetUncheckedFunctions() const {
208     return unchecked_functions_;
209   }
210 
211   void TrimGlobals() REQUIRES_SHARED(Locks::mutator_lock_)
212       REQUIRES(!Locks::jni_globals_lock_);
213 
214   jint HandleGetEnv(/*out*/void** env, jint version)
215       REQUIRES(!env_hooks_lock_);
216 
217   void AddEnvironmentHook(GetEnvHook hook)
218       REQUIRES(!env_hooks_lock_);
219 
220   static bool IsBadJniVersion(int version);
221 
222   // Return the library search path for the given classloader, if the classloader is of a
223   // well-known type. The jobject will be a local reference and is expected to be managed by the
224   // caller.
225   static jstring GetLibrarySearchPath(JNIEnv* env, jobject class_loader);
226 
227  private:
228   // The constructor should not be called directly. Use `Create()` that initializes
229   // the new `JavaVMExt` object by calling `Initialize()`.
230   JavaVMExt(Runtime* runtime, const RuntimeArgumentMap& runtime_options);
231 
232   // Initialize the `JavaVMExt` object.
233   bool Initialize(std::string* error_msg);
234 
235   // Return true if self can currently access weak globals.
236   bool MayAccessWeakGlobals(Thread* self) const REQUIRES_SHARED(Locks::mutator_lock_);
237 
238   void WaitForWeakGlobalsAccess(Thread* self)
239       REQUIRES_SHARED(Locks::mutator_lock_)
240       REQUIRES(Locks::jni_weak_globals_lock_);
241 
242   void CheckGlobalRefAllocationTracking();
243 
244   inline void MaybeTraceGlobals() REQUIRES(Locks::jni_globals_lock_);
245   inline void MaybeTraceWeakGlobals() REQUIRES(Locks::jni_weak_globals_lock_);
246 
247   Runtime* const runtime_;
248 
249   // Used for testing. By default, we'll LOG(FATAL) the reason.
250   void (*check_jni_abort_hook_)(void* data, const std::string& reason);
251   void* check_jni_abort_hook_data_;
252 
253   // Extra checking.
254   bool check_jni_;
255   const bool force_copy_;
256   const bool tracing_enabled_;
257 
258   // Extra diagnostics.
259   const std::string trace_;
260 
261   IndirectReferenceTable globals_;
262 
263   // No lock annotation since UnloadNativeLibraries is called on libraries_ but locks the
264   // jni_libraries_lock_ internally.
265   std::unique_ptr<Libraries> libraries_;
266 
267   // Used by -Xcheck:jni.
268   const JNIInvokeInterface* const unchecked_functions_;
269 
270   // Since weak_globals_ contain weak roots, be careful not to
271   // directly access the object references in it. Use Get() with the
272   // read barrier enabled or disabled based on the use case.
273   IndirectReferenceTable weak_globals_;
274   Atomic<bool> allow_accessing_weak_globals_;
275   ConditionVariable weak_globals_add_condition_ GUARDED_BY(Locks::jni_weak_globals_lock_);
276 
277   // TODO Maybe move this to Runtime.
278   ReaderWriterMutex env_hooks_lock_ BOTTOM_MUTEX_ACQUIRED_AFTER;
279   std::vector<GetEnvHook> env_hooks_ GUARDED_BY(env_hooks_lock_);
280 
281   size_t enable_allocation_tracking_delta_;
282   std::atomic<bool> allocation_tracking_enabled_;
283   std::atomic<bool> old_allocation_tracking_state_;
284 
285   // We report the number of global references after every kGlobalRefReportInterval changes.
286   static constexpr uint32_t kGlobalRefReportInterval = 17;
287   uint32_t weak_global_ref_report_counter_ GUARDED_BY(Locks::jni_weak_globals_lock_)
288       = kGlobalRefReportInterval;
289   uint32_t global_ref_report_counter_ GUARDED_BY(Locks::jni_globals_lock_)
290       = kGlobalRefReportInterval;
291 
292   friend class linker::ImageWriter;  // Uses `globals_` and `weak_globals_` without read barrier.
293   friend IndirectReferenceTable* GetIndirectReferenceTable(ScopedObjectAccess& soa,
294                                                            IndirectRefKind kind);
295 
296   DISALLOW_COPY_AND_ASSIGN(JavaVMExt);
297 };
298 
299 }  // namespace art
300 
301 #endif  // ART_RUNTIME_JNI_JAVA_VM_EXT_H_
302