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