Elliott Hughes | 2faa5f1 | 2012-01-30 14:42:07 -0800 | [diff] [blame] | 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 | */ |
Elliott Hughes | c5bfa8f | 2011-08-30 14:32:49 -0700 | [diff] [blame] | 16 | |
| 17 | #include "jni_internal.h" |
| 18 | |
| 19 | namespace art { |
| 20 | |
| 21 | // Entry/exit processing for all JNI calls. |
| 22 | // |
| 23 | // This performs the necessary thread state switching, lets us amortize the |
| 24 | // cost of working out the current thread, and lets us check (and repair) apps |
| 25 | // that are using a JNIEnv on the wrong thread. |
| 26 | class ScopedJniThreadState { |
| 27 | public: |
| 28 | explicit ScopedJniThreadState(JNIEnv* env) |
| 29 | : env_(reinterpret_cast<JNIEnvExt*>(env)) { |
| 30 | self_ = ThreadForEnv(env); |
Elliott Hughes | 34e0696 | 2012-04-09 13:55:55 -0700 | [diff] [blame] | 31 | old_thread_state_ = self_->SetState(kRunnable); |
jeffhao | 2504552 | 2012-03-13 19:34:37 -0700 | [diff] [blame] | 32 | self_->VerifyStack(); |
Elliott Hughes | c5bfa8f | 2011-08-30 14:32:49 -0700 | [diff] [blame] | 33 | } |
| 34 | |
| 35 | ~ScopedJniThreadState() { |
Elliott Hughes | ad7c2a3 | 2011-08-31 11:58:10 -0700 | [diff] [blame] | 36 | self_->SetState(old_thread_state_); |
Elliott Hughes | c5bfa8f | 2011-08-30 14:32:49 -0700 | [diff] [blame] | 37 | } |
| 38 | |
| 39 | JNIEnvExt* Env() { |
| 40 | return env_; |
| 41 | } |
| 42 | |
| 43 | Thread* Self() { |
| 44 | return self_; |
| 45 | } |
| 46 | |
| 47 | JavaVMExt* Vm() { |
| 48 | return env_->vm; |
| 49 | } |
| 50 | |
| 51 | private: |
| 52 | static Thread* ThreadForEnv(JNIEnv* env) { |
| 53 | JNIEnvExt* full_env(reinterpret_cast<JNIEnvExt*>(env)); |
Elliott Hughes | b264f08 | 2012-04-06 17:10:10 -0700 | [diff] [blame] | 54 | bool work_around_app_jni_bugs = full_env->vm->work_around_app_jni_bugs; |
Elliott Hughes | c5bfa8f | 2011-08-30 14:32:49 -0700 | [diff] [blame] | 55 | Thread* env_self = full_env->self; |
Elliott Hughes | b264f08 | 2012-04-06 17:10:10 -0700 | [diff] [blame] | 56 | Thread* self = work_around_app_jni_bugs ? Thread::Current() : env_self; |
| 57 | if (!work_around_app_jni_bugs && self != env_self) { |
| 58 | LOG(FATAL) << "JNI ERROR (app bug): JNIEnv for " << *env_self |
Elliott Hughes | c5bfa8f | 2011-08-30 14:32:49 -0700 | [diff] [blame] | 59 | << " used on " << *self; |
Elliott Hughes | b264f08 | 2012-04-06 17:10:10 -0700 | [diff] [blame] | 60 | // TODO: pass JNI function through so we can call JniAbort(function_name) instead. |
Elliott Hughes | c5bfa8f | 2011-08-30 14:32:49 -0700 | [diff] [blame] | 61 | } |
| 62 | return self; |
| 63 | } |
| 64 | |
| 65 | JNIEnvExt* env_; |
| 66 | Thread* self_; |
Elliott Hughes | 34e0696 | 2012-04-09 13:55:55 -0700 | [diff] [blame] | 67 | ThreadState old_thread_state_; |
Elliott Hughes | c5bfa8f | 2011-08-30 14:32:49 -0700 | [diff] [blame] | 68 | DISALLOW_COPY_AND_ASSIGN(ScopedJniThreadState); |
| 69 | }; |
| 70 | |
| 71 | } // namespace art |