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