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 mirror {
31 class Array;
32 }  // namespace mirror
33 
34 class ArtMethod;
35 class IsMarkedVisitor;
36 class Libraries;
37 class ParsedOptions;
38 class Runtime;
39 struct RuntimeArgumentMap;
40 
41 class JavaVMExt;
42 // Hook definition for runtime plugins.
43 using GetEnvHook = jint (*)(JavaVMExt* vm, /*out*/void** new_env, jint version);
44 
45 class JavaVMExt : public JavaVM {
46  public:
47   // Creates a new JavaVMExt object.
48   // Returns nullptr on error, in which case error_msg is set to a message
49   // describing the error.
50   static std::unique_ptr<JavaVMExt> Create(Runtime* runtime,
51                                            const RuntimeArgumentMap& runtime_options,
52                                            std::string* error_msg);
53 
54 
55   ~JavaVMExt();
56 
ForceCopy()57   bool ForceCopy() const {
58     return force_copy_;
59   }
60 
IsCheckJniEnabled()61   bool IsCheckJniEnabled() const {
62     return check_jni_;
63   }
64 
IsTracingEnabled()65   bool IsTracingEnabled() const {
66     return tracing_enabled_;
67   }
68 
GetRuntime()69   Runtime* GetRuntime() const {
70     return runtime_;
71   }
72 
SetCheckJniAbortHook(void (* hook)(void *,const std::string &),void * data)73   void SetCheckJniAbortHook(void (*hook)(void*, const std::string&), void* data) {
74     check_jni_abort_hook_ = hook;
75     check_jni_abort_hook_data_ = data;
76   }
77 
78   // Aborts execution unless there is an abort handler installed in which case it will return. Its
79   // therefore important that callers return after aborting as otherwise code following the abort
80   // will be executed in the abort handler case.
81   void JniAbort(const char* jni_function_name, const char* msg);
82 
83   void JniAbortV(const char* jni_function_name, const char* fmt, va_list ap);
84 
85   void JniAbortF(const char* jni_function_name, const char* fmt, ...)
86       __attribute__((__format__(__printf__, 3, 4)));
87 
88   // If both "-Xcheck:jni" and "-Xjnitrace:" are enabled, we print trace messages
89   // when a native method that matches the -Xjnitrace argument calls a JNI function
90   // such as NewByteArray.
91   // If -verbose:third-party-jni is on, we want to log any JNI function calls
92   // made by a third-party native method.
93   bool ShouldTrace(ArtMethod* method) REQUIRES_SHARED(Locks::mutator_lock_);
94 
95   /**
96    * Loads the given shared library. 'path' is an absolute pathname.
97    *
98    * Returns 'true' on success. On failure, sets 'error_msg' to a
99    * human-readable description of the error.
100    */
101   bool LoadNativeLibrary(JNIEnv* env,
102                          const std::string& path,
103                          jobject class_loader,
104                          jclass caller_class,
105                          std::string* error_msg);
106 
107   // Unload native libraries with cleared class loaders.
108   void UnloadNativeLibraries()
109       REQUIRES(!Locks::jni_libraries_lock_)
110       REQUIRES_SHARED(Locks::mutator_lock_);
111 
112   // Unload all boot classpath native libraries.
113   void UnloadBootNativeLibraries()
114       REQUIRES(!Locks::jni_libraries_lock_)
115       REQUIRES_SHARED(Locks::mutator_lock_);
116 
117   /**
118    * Returns a pointer to the code for the native method 'm', found
119    * using dlsym(3) on every native library that's been loaded so far.
120    */
121   void* FindCodeForNativeMethod(ArtMethod* m)
122       REQUIRES_SHARED(Locks::mutator_lock_);
123 
124   void DumpForSigQuit(std::ostream& os)
125       REQUIRES(!Locks::jni_libraries_lock_,
126                !Locks::jni_globals_lock_,
127                !Locks::jni_weak_globals_lock_);
128 
129   void DumpReferenceTables(std::ostream& os)
130       REQUIRES_SHARED(Locks::mutator_lock_)
131       REQUIRES(!Locks::jni_globals_lock_,
132                !Locks::jni_weak_globals_lock_,
133                !Locks::alloc_tracker_lock_);
134 
135   bool SetCheckJniEnabled(bool enabled);
136 
137   void VisitRoots(RootVisitor* visitor) REQUIRES_SHARED(Locks::mutator_lock_)
138       REQUIRES(!Locks::jni_globals_lock_);
139 
140   void DisallowNewWeakGlobals()
141       REQUIRES_SHARED(Locks::mutator_lock_)
142       REQUIRES(!Locks::jni_weak_globals_lock_);
143   void AllowNewWeakGlobals()
144       REQUIRES_SHARED(Locks::mutator_lock_)
145       REQUIRES(!Locks::jni_weak_globals_lock_);
146   void BroadcastForNewWeakGlobals()
147       REQUIRES(!Locks::jni_weak_globals_lock_);
148 
149   jobject AddGlobalRef(Thread* self, ObjPtr<mirror::Object> obj)
150       REQUIRES_SHARED(Locks::mutator_lock_)
151       REQUIRES(!Locks::jni_globals_lock_);
152 
153   jweak AddWeakGlobalRef(Thread* self, ObjPtr<mirror::Object> obj)
154       REQUIRES_SHARED(Locks::mutator_lock_)
155       REQUIRES(!Locks::jni_weak_globals_lock_);
156 
157   void DeleteGlobalRef(Thread* self, jobject obj) REQUIRES(!Locks::jni_globals_lock_);
158 
159   void DeleteWeakGlobalRef(Thread* self, jweak obj) REQUIRES(!Locks::jni_weak_globals_lock_);
160 
161   void SweepJniWeakGlobals(IsMarkedVisitor* visitor)
162       REQUIRES_SHARED(Locks::mutator_lock_)
163       REQUIRES(!Locks::jni_weak_globals_lock_);
164 
165   ObjPtr<mirror::Object> DecodeGlobal(IndirectRef ref)
166       REQUIRES_SHARED(Locks::mutator_lock_);
167 
168   void UpdateGlobal(Thread* self, IndirectRef ref, ObjPtr<mirror::Object> result)
169       REQUIRES_SHARED(Locks::mutator_lock_)
170       REQUIRES(!Locks::jni_globals_lock_);
171 
172   ObjPtr<mirror::Object> DecodeWeakGlobal(Thread* self, IndirectRef ref)
173       REQUIRES_SHARED(Locks::mutator_lock_)
174       REQUIRES(!Locks::jni_weak_globals_lock_);
175 
176   ObjPtr<mirror::Object> DecodeWeakGlobalLocked(Thread* self, IndirectRef ref)
177       REQUIRES_SHARED(Locks::mutator_lock_)
178       REQUIRES(Locks::jni_weak_globals_lock_);
179 
180   // Like DecodeWeakGlobal() but to be used only during a runtime shutdown where self may be
181   // null.
182   ObjPtr<mirror::Object> DecodeWeakGlobalDuringShutdown(Thread* self, IndirectRef ref)
183       REQUIRES_SHARED(Locks::mutator_lock_)
184       REQUIRES(!Locks::jni_weak_globals_lock_);
185 
186   // Checks if the weak global ref has been cleared by the GC without decode (read barrier.)
187   bool IsWeakGlobalCleared(Thread* self, IndirectRef ref)
188       REQUIRES_SHARED(Locks::mutator_lock_)
189       REQUIRES(!Locks::jni_weak_globals_lock_);
190 
191   void UpdateWeakGlobal(Thread* self, IndirectRef ref, ObjPtr<mirror::Object> result)
192       REQUIRES_SHARED(Locks::mutator_lock_)
193       REQUIRES(!Locks::jni_weak_globals_lock_);
194 
GetUncheckedFunctions()195   const JNIInvokeInterface* GetUncheckedFunctions() const {
196     return unchecked_functions_;
197   }
198 
199   void TrimGlobals() REQUIRES_SHARED(Locks::mutator_lock_)
200       REQUIRES(!Locks::jni_globals_lock_);
201 
202   jint HandleGetEnv(/*out*/void** env, jint version);
203 
204   void AddEnvironmentHook(GetEnvHook hook);
205 
206   static bool IsBadJniVersion(int version);
207 
208   // Return the library search path for the given classloader, if the classloader is of a
209   // well-known type. The jobject will be a local reference and is expected to be managed by the
210   // caller.
211   static jstring GetLibrarySearchPath(JNIEnv* env, jobject class_loader);
212 
213  private:
214   // The constructor should not be called directly. It may leave the object in
215   // an erroneous state, and the result needs to be checked.
216   JavaVMExt(Runtime* runtime, const RuntimeArgumentMap& runtime_options, std::string* error_msg);
217 
218   // Return true if self can currently access weak globals.
219   bool MayAccessWeakGlobalsUnlocked(Thread* self) const REQUIRES_SHARED(Locks::mutator_lock_);
220   bool MayAccessWeakGlobals(Thread* self) const
221       REQUIRES_SHARED(Locks::mutator_lock_)
222       REQUIRES(Locks::jni_weak_globals_lock_);
223 
224   void CheckGlobalRefAllocationTracking();
225 
226   Runtime* const runtime_;
227 
228   // Used for testing. By default, we'll LOG(FATAL) the reason.
229   void (*check_jni_abort_hook_)(void* data, const std::string& reason);
230   void* check_jni_abort_hook_data_;
231 
232   // Extra checking.
233   bool check_jni_;
234   const bool force_copy_;
235   const bool tracing_enabled_;
236 
237   // Extra diagnostics.
238   const std::string trace_;
239 
240   // Not guarded by globals_lock since we sometimes use SynchronizedGet in Thread::DecodeJObject.
241   IndirectReferenceTable globals_;
242 
243   // No lock annotation since UnloadNativeLibraries is called on libraries_ but locks the
244   // jni_libraries_lock_ internally.
245   std::unique_ptr<Libraries> libraries_;
246 
247   // Used by -Xcheck:jni.
248   const JNIInvokeInterface* const unchecked_functions_;
249 
250   // Since weak_globals_ contain weak roots, be careful not to
251   // directly access the object references in it. Use Get() with the
252   // read barrier enabled.
253   // Not guarded by weak_globals_lock since we may use SynchronizedGet in DecodeWeakGlobal.
254   IndirectReferenceTable weak_globals_;
255   // Not guarded by weak_globals_lock since we may use SynchronizedGet in DecodeWeakGlobal.
256   Atomic<bool> allow_accessing_weak_globals_;
257   ConditionVariable weak_globals_add_condition_ GUARDED_BY(Locks::jni_weak_globals_lock_);
258 
259   // TODO Maybe move this to Runtime.
260   std::vector<GetEnvHook> env_hooks_;
261 
262   size_t enable_allocation_tracking_delta_;
263   std::atomic<bool> allocation_tracking_enabled_;
264   std::atomic<bool> old_allocation_tracking_state_;
265 
266   DISALLOW_COPY_AND_ASSIGN(JavaVMExt);
267 };
268 
269 }  // namespace art
270 
271 #endif  // ART_RUNTIME_JNI_JAVA_VM_EXT_H_
272