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_INTERNAL_H_ 18 #define ART_RUNTIME_JNI_INTERNAL_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 "reference_table.h" 26 #include "root_visitor.h" 27 #include "runtime.h" 28 29 #include <iosfwd> 30 #include <string> 31 32 #ifndef NATIVE_METHOD 33 #define NATIVE_METHOD(className, functionName, signature) \ 34 { #functionName, signature, reinterpret_cast<void*>(className ## _ ## functionName) } 35 #endif 36 #define REGISTER_NATIVE_METHODS(jni_class_name) \ 37 RegisterNativeMethods(env, jni_class_name, gMethods, arraysize(gMethods)) 38 39 namespace art { 40 namespace mirror { 41 class ArtField; 42 class ArtMethod; 43 class ClassLoader; 44 } // namespace mirror 45 class ArgArray; 46 union JValue; 47 class Libraries; 48 class ScopedObjectAccess; 49 class Thread; 50 51 void JniAbortF(const char* jni_function_name, const char* fmt, ...) 52 __attribute__((__format__(__printf__, 2, 3))); 53 void RegisterNativeMethods(JNIEnv* env, const char* jni_class_name, const JNINativeMethod* methods, 54 jint method_count); 55 56 JValue InvokeWithJValues(const ScopedObjectAccess&, jobject obj, jmethodID mid, jvalue* args) 57 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 58 void InvokeWithArgArray(const ScopedObjectAccess& soa, mirror::ArtMethod* method, 59 ArgArray *arg_array, JValue* result, char result_type) 60 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 61 62 int ThrowNewException(JNIEnv* env, jclass exception_class, const char* msg, jobject cause); 63 64 class JavaVMExt : public JavaVM { 65 public: 66 JavaVMExt(Runtime* runtime, Runtime::ParsedOptions* options); 67 ~JavaVMExt(); 68 69 /** 70 * Loads the given shared library. 'path' is an absolute pathname. 71 * 72 * Returns 'true' on success. On failure, sets 'detail' to a 73 * human-readable description of the error. 74 */ 75 bool LoadNativeLibrary(const std::string& path, mirror::ClassLoader* class_loader, 76 std::string& detail) 77 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 78 79 /** 80 * Returns a pointer to the code for the native method 'm', found 81 * using dlsym(3) on every native library that's been loaded so far. 82 */ 83 void* FindCodeForNativeMethod(mirror::ArtMethod* m) 84 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 85 86 void DumpForSigQuit(std::ostream& os); 87 88 void DumpReferenceTables(std::ostream& os) 89 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 90 91 void SetCheckJniEnabled(bool enabled); 92 93 void VisitRoots(RootVisitor*, void*); 94 95 void DisallowNewWeakGlobals() EXCLUSIVE_LOCKS_REQUIRED(Locks::mutator_lock_); 96 void AllowNewWeakGlobals() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 97 jweak AddWeakGlobalReference(Thread* self, mirror::Object* obj) 98 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 99 void DeleteWeakGlobalRef(Thread* self, jweak obj) 100 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 101 void SweepWeakGlobals(IsMarkedTester is_marked, void* arg); 102 mirror::Object* DecodeWeakGlobal(Thread* self, IndirectRef ref); 103 104 Runtime* runtime; 105 106 // Used for testing. By default, we'll LOG(FATAL) the reason. 107 void (*check_jni_abort_hook)(void* data, const std::string& reason); 108 void* check_jni_abort_hook_data; 109 110 // Extra checking. 111 bool check_jni; 112 bool force_copy; 113 114 // Extra diagnostics. 115 std::string trace; 116 117 // Used to provide compatibility for apps that assumed direct references. 118 bool work_around_app_jni_bugs; 119 120 // Used to hold references to pinned primitive arrays. 121 Mutex pins_lock DEFAULT_MUTEX_ACQUIRED_AFTER; 122 ReferenceTable pin_table GUARDED_BY(pins_lock); 123 124 // JNI global references. 125 ReaderWriterMutex globals_lock DEFAULT_MUTEX_ACQUIRED_AFTER; 126 IndirectReferenceTable globals GUARDED_BY(globals_lock); 127 128 Mutex libraries_lock DEFAULT_MUTEX_ACQUIRED_AFTER; 129 Libraries* libraries GUARDED_BY(libraries_lock); 130 131 // Used by -Xcheck:jni. 132 const JNIInvokeInterface* unchecked_functions; 133 134 private: 135 // TODO: Make the other members of this class also private. 136 // JNI weak global references. 137 Mutex weak_globals_lock_ DEFAULT_MUTEX_ACQUIRED_AFTER; 138 IndirectReferenceTable weak_globals_ GUARDED_BY(weak_globals_lock_); 139 bool allow_new_weak_globals_ GUARDED_BY(weak_globals_lock_); 140 ConditionVariable weak_globals_add_condition_ GUARDED_BY(weak_globals_lock_); 141 }; 142 143 struct JNIEnvExt : public JNIEnv { 144 JNIEnvExt(Thread* self, JavaVMExt* vm); 145 ~JNIEnvExt(); 146 147 void DumpReferenceTables(std::ostream& os) 148 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 149 150 void SetCheckJniEnabled(bool enabled); 151 152 void PushFrame(int capacity); 153 void PopFrame(); 154 155 static Offset SegmentStateOffset(); 156 157 static Offset LocalRefCookieOffset() { 158 return Offset(OFFSETOF_MEMBER(JNIEnvExt, local_ref_cookie)); 159 } 160 161 static Offset SelfOffset() { 162 return Offset(OFFSETOF_MEMBER(JNIEnvExt, self)); 163 } 164 165 Thread* const self; 166 JavaVMExt* vm; 167 168 // Cookie used when using the local indirect reference table. 169 uint32_t local_ref_cookie; 170 171 // JNI local references. 172 IndirectReferenceTable locals; 173 174 // Stack of cookies corresponding to PushLocalFrame/PopLocalFrame calls. 175 // TODO: to avoid leaks (and bugs), we need to clear this vector on entry (or return) 176 // to a native method. 177 std::vector<uint32_t> stacked_local_ref_cookies; 178 179 // Frequently-accessed fields cached from JavaVM. 180 bool check_jni; 181 182 // How many nested "critical" JNI calls are we in? 183 int critical; 184 185 // Entered JNI monitors, for bulk exit on thread detach. 186 ReferenceTable monitors; 187 188 // Used by -Xcheck:jni. 189 const JNINativeInterface* unchecked_functions; 190 }; 191 192 const JNINativeInterface* GetCheckJniNativeInterface(); 193 const JNIInvokeInterface* GetCheckJniInvokeInterface(); 194 195 // Used to save and restore the JNIEnvExt state when not going through code created by the JNI 196 // compiler 197 class ScopedJniEnvLocalRefState { 198 public: 199 explicit ScopedJniEnvLocalRefState(JNIEnvExt* env) : env_(env) { 200 saved_local_ref_cookie_ = env->local_ref_cookie; 201 env->local_ref_cookie = env->locals.GetSegmentState(); 202 } 203 204 ~ScopedJniEnvLocalRefState() { 205 env_->locals.SetSegmentState(env_->local_ref_cookie); 206 env_->local_ref_cookie = saved_local_ref_cookie_; 207 } 208 209 private: 210 JNIEnvExt* env_; 211 uint32_t saved_local_ref_cookie_; 212 DISALLOW_COPY_AND_ASSIGN(ScopedJniEnvLocalRefState); 213 }; 214 215 } // namespace art 216 217 std::ostream& operator<<(std::ostream& os, const jobjectRefType& rhs); 218 219 #endif // ART_RUNTIME_JNI_INTERNAL_H_ 220