• 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 
166   void SweepJniWeakGlobals(IsMarkedVisitor* visitor)
167       REQUIRES_SHARED(Locks::mutator_lock_)
168       REQUIRES(!Locks::jni_weak_globals_lock_);
169 
170   ObjPtr<mirror::Object> DecodeGlobal(IndirectRef ref)
171       REQUIRES_SHARED(Locks::mutator_lock_);
172 
173   void UpdateGlobal(Thread* self, IndirectRef ref, ObjPtr<mirror::Object> result)
174       REQUIRES_SHARED(Locks::mutator_lock_)
175       REQUIRES(!Locks::jni_globals_lock_);
176 
177   ObjPtr<mirror::Object> DecodeWeakGlobal(Thread* self, IndirectRef ref)
178       REQUIRES_SHARED(Locks::mutator_lock_)
179       REQUIRES(!Locks::jni_weak_globals_lock_);
180 
181   ObjPtr<mirror::Object> DecodeWeakGlobalLocked(Thread* self, IndirectRef ref)
182       REQUIRES_SHARED(Locks::mutator_lock_)
183       REQUIRES(Locks::jni_weak_globals_lock_);
184 
185   // Like DecodeWeakGlobal() but to be used only during a runtime shutdown where self may be
186   // null.
187   ObjPtr<mirror::Object> DecodeWeakGlobalDuringShutdown(Thread* self, IndirectRef ref)
188       REQUIRES_SHARED(Locks::mutator_lock_)
189       REQUIRES(!Locks::jni_weak_globals_lock_);
190 
191   // Checks if the weak global ref has been cleared by the GC without decode (read barrier.)
192   bool IsWeakGlobalCleared(Thread* self, IndirectRef ref)
193       REQUIRES_SHARED(Locks::mutator_lock_)
194       REQUIRES(!Locks::jni_weak_globals_lock_);
195 
196   void UpdateWeakGlobal(Thread* self, IndirectRef ref, ObjPtr<mirror::Object> result)
197       REQUIRES_SHARED(Locks::mutator_lock_)
198       REQUIRES(!Locks::jni_weak_globals_lock_);
199 
GetUncheckedFunctions()200   const JNIInvokeInterface* GetUncheckedFunctions() const {
201     return unchecked_functions_;
202   }
203 
204   void TrimGlobals() REQUIRES_SHARED(Locks::mutator_lock_)
205       REQUIRES(!Locks::jni_globals_lock_);
206 
207   jint HandleGetEnv(/*out*/void** env, jint version)
208       REQUIRES(!env_hooks_lock_);
209 
210   void AddEnvironmentHook(GetEnvHook hook)
211       REQUIRES(!env_hooks_lock_);
212 
213   static bool IsBadJniVersion(int version);
214 
215   // Return the library search path for the given classloader, if the classloader is of a
216   // well-known type. The jobject will be a local reference and is expected to be managed by the
217   // caller.
218   static jstring GetLibrarySearchPath(JNIEnv* env, jobject class_loader);
219 
220  private:
221   // The constructor should not be called directly. It may leave the object in
222   // an erroneous state, and the result needs to be checked.
223   JavaVMExt(Runtime* runtime, const RuntimeArgumentMap& runtime_options, std::string* error_msg);
224 
225   // Return true if self can currently access weak globals.
226   bool MayAccessWeakGlobals(Thread* self) const REQUIRES_SHARED(Locks::mutator_lock_);
227 
228   void WaitForWeakGlobalsAccess(Thread* self)
229       REQUIRES_SHARED(Locks::mutator_lock_)
230       REQUIRES(Locks::jni_weak_globals_lock_);
231 
232   void CheckGlobalRefAllocationTracking();
233 
234   inline void MaybeTraceGlobals() REQUIRES(Locks::jni_globals_lock_);
235   inline void MaybeTraceWeakGlobals() REQUIRES(Locks::jni_weak_globals_lock_);
236 
237   Runtime* const runtime_;
238 
239   // Used for testing. By default, we'll LOG(FATAL) the reason.
240   void (*check_jni_abort_hook_)(void* data, const std::string& reason);
241   void* check_jni_abort_hook_data_;
242 
243   // Extra checking.
244   bool check_jni_;
245   const bool force_copy_;
246   const bool tracing_enabled_;
247 
248   // Extra diagnostics.
249   const std::string trace_;
250 
251   // Not guarded by globals_lock since we sometimes use SynchronizedGet in Thread::DecodeJObject.
252   IndirectReferenceTable globals_;
253 
254   // No lock annotation since UnloadNativeLibraries is called on libraries_ but locks the
255   // jni_libraries_lock_ internally.
256   std::unique_ptr<Libraries> libraries_;
257 
258   // Used by -Xcheck:jni.
259   const JNIInvokeInterface* const unchecked_functions_;
260 
261   // Since weak_globals_ contain weak roots, be careful not to
262   // directly access the object references in it. Use Get() with the
263   // read barrier enabled.
264   // Not guarded by weak_globals_lock since we may use SynchronizedGet in DecodeWeakGlobal.
265   IndirectReferenceTable weak_globals_;
266   // Not guarded by weak_globals_lock since we may use SynchronizedGet in DecodeWeakGlobal.
267   Atomic<bool> allow_accessing_weak_globals_;
268   ConditionVariable weak_globals_add_condition_ GUARDED_BY(Locks::jni_weak_globals_lock_);
269 
270   // TODO Maybe move this to Runtime.
271   ReaderWriterMutex env_hooks_lock_ BOTTOM_MUTEX_ACQUIRED_AFTER;
272   std::vector<GetEnvHook> env_hooks_ GUARDED_BY(env_hooks_lock_);
273 
274   size_t enable_allocation_tracking_delta_;
275   std::atomic<bool> allocation_tracking_enabled_;
276   std::atomic<bool> old_allocation_tracking_state_;
277 
278   // We report the number of global references after every kGlobalRefReportInterval changes.
279   static constexpr uint32_t kGlobalRefReportInterval = 17;
280   uint32_t weak_global_ref_report_counter_ GUARDED_BY(Locks::jni_weak_globals_lock_)
281       = kGlobalRefReportInterval;
282   uint32_t global_ref_report_counter_ GUARDED_BY(Locks::jni_globals_lock_)
283       = kGlobalRefReportInterval;
284 
285   friend class linker::ImageWriter;  // Uses `globals_` and `weak_globals_` without read barrier.
286   friend IndirectReferenceTable* GetIndirectReferenceTable(ScopedObjectAccess& soa,
287                                                            IndirectRefKind kind);
288 
289   DISALLOW_COPY_AND_ASSIGN(JavaVMExt);
290 };
291 
292 }  // namespace art
293 
294 #endif  // ART_RUNTIME_JNI_JAVA_VM_EXT_H_
295