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