jni_env_ext.cc revision da0a69edb24122d3d35ce1483c5ab94de919d714
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#include "jni_env_ext.h" 18 19#include <algorithm> 20#include <vector> 21 22#include "check_jni.h" 23#include "indirect_reference_table.h" 24#include "java_vm_ext.h" 25#include "jni_internal.h" 26#include "lock_word.h" 27#include "mirror/object-inl.h" 28#include "nth_caller_visitor.h" 29#include "thread-inl.h" 30 31namespace art { 32 33static constexpr size_t kMonitorsInitial = 32; // Arbitrary. 34static constexpr size_t kMonitorsMax = 4096; // Arbitrary sanity check. 35 36// Checking "locals" requires the mutator lock, but at creation time we're really only interested 37// in validity, which isn't changing. To avoid grabbing the mutator lock, factored out and tagged 38// with NO_THREAD_SAFETY_ANALYSIS. 39static bool CheckLocalsValid(JNIEnvExt* in) NO_THREAD_SAFETY_ANALYSIS { 40 if (in == nullptr) { 41 return false; 42 } 43 return in->locals.IsValid(); 44} 45 46jint JNIEnvExt::GetEnvHandler(JavaVMExt* vm, /*out*/void** env, jint version) { 47 UNUSED(vm); 48 // GetEnv always returns a JNIEnv* for the most current supported JNI version, 49 // and unlike other calls that take a JNI version doesn't care if you supply 50 // JNI_VERSION_1_1, which we don't otherwise support. 51 if (JavaVMExt::IsBadJniVersion(version) && version != JNI_VERSION_1_1) { 52 return JNI_EVERSION; 53 } 54 Thread* thread = Thread::Current(); 55 CHECK(thread != nullptr); 56 *env = thread->GetJniEnv(); 57 return JNI_OK; 58} 59 60JNIEnvExt* JNIEnvExt::Create(Thread* self_in, JavaVMExt* vm_in, std::string* error_msg) { 61 std::unique_ptr<JNIEnvExt> ret(new JNIEnvExt(self_in, vm_in, error_msg)); 62 if (CheckLocalsValid(ret.get())) { 63 return ret.release(); 64 } 65 return nullptr; 66} 67 68JNIEnvExt::JNIEnvExt(Thread* self_in, JavaVMExt* vm_in, std::string* error_msg) 69 : self(self_in), 70 vm(vm_in), 71 local_ref_cookie(IRT_FIRST_SEGMENT), 72 locals(kLocalsInitial, kLocal, error_msg), 73 check_jni(false), 74 runtime_deleted(false), 75 critical(0), 76 monitors("monitors", kMonitorsInitial, kMonitorsMax) { 77 functions = unchecked_functions = GetJniNativeInterface(); 78 if (vm->IsCheckJniEnabled()) { 79 SetCheckJniEnabled(true); 80 } 81} 82 83void JNIEnvExt::SetFunctionsToRuntimeShutdownFunctions() { 84 functions = GetRuntimeShutdownNativeInterface(); 85 runtime_deleted = true; 86} 87 88JNIEnvExt::~JNIEnvExt() { 89} 90 91jobject JNIEnvExt::NewLocalRef(mirror::Object* obj) { 92 if (obj == nullptr) { 93 return nullptr; 94 } 95 return reinterpret_cast<jobject>(locals.Add(local_ref_cookie, obj)); 96} 97 98void JNIEnvExt::DeleteLocalRef(jobject obj) { 99 if (obj != nullptr) { 100 locals.Remove(local_ref_cookie, reinterpret_cast<IndirectRef>(obj)); 101 } 102} 103 104void JNIEnvExt::SetCheckJniEnabled(bool enabled) { 105 check_jni = enabled; 106 functions = enabled ? GetCheckJniNativeInterface() : GetJniNativeInterface(); 107} 108 109void JNIEnvExt::DumpReferenceTables(std::ostream& os) { 110 locals.Dump(os); 111 monitors.Dump(os); 112} 113 114void JNIEnvExt::PushFrame(int capacity ATTRIBUTE_UNUSED) { 115 // TODO: take 'capacity' into account. 116 stacked_local_ref_cookies.push_back(local_ref_cookie); 117 local_ref_cookie = locals.GetSegmentState(); 118} 119 120void JNIEnvExt::PopFrame() { 121 locals.SetSegmentState(local_ref_cookie); 122 local_ref_cookie = stacked_local_ref_cookies.back(); 123 stacked_local_ref_cookies.pop_back(); 124} 125 126// Note: the offset code is brittle, as we can't use OFFSETOF_MEMBER or offsetof easily. Thus, there 127// are tests in jni_internal_test to match the results against the actual values. 128 129// This is encoding the knowledge of the structure and layout of JNIEnv fields. 130static size_t JNIEnvSize(size_t pointer_size) { 131 // A single pointer. 132 return pointer_size; 133} 134 135Offset JNIEnvExt::SegmentStateOffset(size_t pointer_size) { 136 size_t locals_offset = JNIEnvSize(pointer_size) + 137 2 * pointer_size + // Thread* self + JavaVMExt* vm. 138 4 + // local_ref_cookie. 139 (pointer_size - 4); // Padding. 140 size_t irt_segment_state_offset = 141 IndirectReferenceTable::SegmentStateOffset(pointer_size).Int32Value(); 142 return Offset(locals_offset + irt_segment_state_offset); 143} 144 145Offset JNIEnvExt::LocalRefCookieOffset(size_t pointer_size) { 146 return Offset(JNIEnvSize(pointer_size) + 147 2 * pointer_size); // Thread* self + JavaVMExt* vm 148} 149 150Offset JNIEnvExt::SelfOffset(size_t pointer_size) { 151 return Offset(JNIEnvSize(pointer_size)); 152} 153 154// Use some defining part of the caller's frame as the identifying mark for the JNI segment. 155static uintptr_t GetJavaCallFrame(Thread* self) REQUIRES_SHARED(Locks::mutator_lock_) { 156 NthCallerVisitor zeroth_caller(self, 0, false); 157 zeroth_caller.WalkStack(); 158 if (zeroth_caller.caller == nullptr) { 159 // No Java code, must be from pure native code. 160 return 0; 161 } else if (zeroth_caller.GetCurrentQuickFrame() == nullptr) { 162 // Shadow frame = interpreter. Use the actual shadow frame's address. 163 DCHECK(zeroth_caller.GetCurrentShadowFrame() != nullptr); 164 return reinterpret_cast<uintptr_t>(zeroth_caller.GetCurrentShadowFrame()); 165 } else { 166 // Quick frame = compiled code. Use the bottom of the frame. 167 return reinterpret_cast<uintptr_t>(zeroth_caller.GetCurrentQuickFrame()); 168 } 169} 170 171void JNIEnvExt::RecordMonitorEnter(jobject obj) { 172 locked_objects_.push_back(std::make_pair(GetJavaCallFrame(self), obj)); 173} 174 175static std::string ComputeMonitorDescription(Thread* self, 176 jobject obj) REQUIRES_SHARED(Locks::mutator_lock_) { 177 ObjPtr<mirror::Object> o = self->DecodeJObject(obj); 178 if ((o->GetLockWord(false).GetState() == LockWord::kThinLocked) && 179 Locks::mutator_lock_->IsExclusiveHeld(self)) { 180 // Getting the identity hashcode here would result in lock inflation and suspension of the 181 // current thread, which isn't safe if this is the only runnable thread. 182 return StringPrintf("<@addr=0x%" PRIxPTR "> (a %s)", 183 reinterpret_cast<intptr_t>(o.Ptr()), 184 PrettyTypeOf(o).c_str()); 185 } else { 186 // IdentityHashCode can cause thread suspension, which would invalidate o if it moved. So 187 // we get the pretty type before we call IdentityHashCode. 188 const std::string pretty_type(PrettyTypeOf(o)); 189 return StringPrintf("<0x%08x> (a %s)", o->IdentityHashCode(), pretty_type.c_str()); 190 } 191} 192 193static void RemoveMonitors(Thread* self, 194 uintptr_t frame, 195 ReferenceTable* monitors, 196 std::vector<std::pair<uintptr_t, jobject>>* locked_objects) 197 REQUIRES_SHARED(Locks::mutator_lock_) { 198 auto kept_end = std::remove_if( 199 locked_objects->begin(), 200 locked_objects->end(), 201 [self, frame, monitors](const std::pair<uintptr_t, jobject>& pair) 202 REQUIRES_SHARED(Locks::mutator_lock_) { 203 if (frame == pair.first) { 204 ObjPtr<mirror::Object> o = self->DecodeJObject(pair.second); 205 monitors->Remove(o); 206 return true; 207 } 208 return false; 209 }); 210 locked_objects->erase(kept_end, locked_objects->end()); 211} 212 213void JNIEnvExt::CheckMonitorRelease(jobject obj) { 214 uintptr_t current_frame = GetJavaCallFrame(self); 215 std::pair<uintptr_t, jobject> exact_pair = std::make_pair(current_frame, obj); 216 auto it = std::find(locked_objects_.begin(), locked_objects_.end(), exact_pair); 217 bool will_abort = false; 218 if (it != locked_objects_.end()) { 219 locked_objects_.erase(it); 220 } else { 221 // Check whether this monitor was locked in another JNI "session." 222 ObjPtr<mirror::Object> mirror_obj = self->DecodeJObject(obj); 223 for (std::pair<uintptr_t, jobject>& pair : locked_objects_) { 224 if (self->DecodeJObject(pair.second) == mirror_obj) { 225 std::string monitor_descr = ComputeMonitorDescription(self, pair.second); 226 vm->JniAbortF("<JNI MonitorExit>", 227 "Unlocking monitor that wasn't locked here: %s", 228 monitor_descr.c_str()); 229 will_abort = true; 230 break; 231 } 232 } 233 } 234 235 // When we abort, also make sure that any locks from the current "session" are removed from 236 // the monitors table, otherwise we may visit local objects in GC during abort (which won't be 237 // valid anymore). 238 if (will_abort) { 239 RemoveMonitors(self, current_frame, &monitors, &locked_objects_); 240 } 241} 242 243void JNIEnvExt::CheckNoHeldMonitors() { 244 uintptr_t current_frame = GetJavaCallFrame(self); 245 // The locked_objects_ are grouped by their stack frame component, as this enforces structured 246 // locking, and the groups form a stack. So the current frame entries are at the end. Check 247 // whether the vector is empty, and when there are elements, whether the last element belongs 248 // to this call - this signals that there are unlocked monitors. 249 if (!locked_objects_.empty()) { 250 std::pair<uintptr_t, jobject>& pair = locked_objects_[locked_objects_.size() - 1]; 251 if (pair.first == current_frame) { 252 std::string monitor_descr = ComputeMonitorDescription(self, pair.second); 253 vm->JniAbortF("<JNI End>", 254 "Still holding a locked object on JNI end: %s", 255 monitor_descr.c_str()); 256 // When we abort, also make sure that any locks from the current "session" are removed from 257 // the monitors table, otherwise we may visit local objects in GC during abort. 258 RemoveMonitors(self, current_frame, &monitors, &locked_objects_); 259 } else if (kIsDebugBuild) { 260 // Make sure there are really no other entries and our checking worked as expected. 261 for (std::pair<uintptr_t, jobject>& check_pair : locked_objects_) { 262 CHECK_NE(check_pair.first, current_frame); 263 } 264 } 265 } 266} 267 268} // namespace art 269