blob: fdf65814c585d6957077b0b50b51af5742b4ed09 [file] [log] [blame]
Elliott Hughes2faa5f12012-01-30 14:42:07 -08001/*
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 Hughesc5bfa8f2011-08-30 14:32:49 -070016
17#include "jni_internal.h"
18
19namespace 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.
26class ScopedJniThreadState {
27 public:
28 explicit ScopedJniThreadState(JNIEnv* env)
29 : env_(reinterpret_cast<JNIEnvExt*>(env)) {
30 self_ = ThreadForEnv(env);
Elliott Hughes34e06962012-04-09 13:55:55 -070031 old_thread_state_ = self_->SetState(kRunnable);
jeffhao25045522012-03-13 19:34:37 -070032 self_->VerifyStack();
Elliott Hughesc5bfa8f2011-08-30 14:32:49 -070033 }
34
35 ~ScopedJniThreadState() {
Elliott Hughesad7c2a32011-08-31 11:58:10 -070036 self_->SetState(old_thread_state_);
Elliott Hughesc5bfa8f2011-08-30 14:32:49 -070037 }
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 Hughesb264f082012-04-06 17:10:10 -070054 bool work_around_app_jni_bugs = full_env->vm->work_around_app_jni_bugs;
Elliott Hughesc5bfa8f2011-08-30 14:32:49 -070055 Thread* env_self = full_env->self;
Elliott Hughesb264f082012-04-06 17:10:10 -070056 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 Hughesc5bfa8f2011-08-30 14:32:49 -070059 << " used on " << *self;
Elliott Hughesb264f082012-04-06 17:10:10 -070060 // TODO: pass JNI function through so we can call JniAbort(function_name) instead.
Elliott Hughesc5bfa8f2011-08-30 14:32:49 -070061 }
62 return self;
63 }
64
65 JNIEnvExt* env_;
66 Thread* self_;
Elliott Hughes34e06962012-04-09 13:55:55 -070067 ThreadState old_thread_state_;
Elliott Hughesc5bfa8f2011-08-30 14:32:49 -070068 DISALLOW_COPY_AND_ASSIGN(ScopedJniThreadState);
69};
70
71} // namespace art