12faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes/*
22faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * Copyright (C) 2011 The Android Open Source Project
32faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes *
42faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * Licensed under the Apache License, Version 2.0 (the "License");
52faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * you may not use this file except in compliance with the License.
62faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * You may obtain a copy of the License at
72faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes *
82faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes *      http://www.apache.org/licenses/LICENSE-2.0
92faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes *
102faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * Unless required by applicable law or agreed to in writing, software
112faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * distributed under the License is distributed on an "AS IS" BASIS,
122faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
132faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * See the License for the specific language governing permissions and
142faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * limitations under the License.
152faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes */
16df20fe0c097073f75f22d16e72fd3636a31d3ca1Ian Rogers
17fc0e3219edc9a5bf81b166e82fd5db2796eb6a0dBrian Carlstrom#ifndef ART_RUNTIME_JNI_INTERNAL_H_
18fc0e3219edc9a5bf81b166e82fd5db2796eb6a0dBrian Carlstrom#define ART_RUNTIME_JNI_INTERNAL_H_
19df20fe0c097073f75f22d16e72fd3636a31d3ca1Ian Rogers
20df20fe0c097073f75f22d16e72fd3636a31d3ca1Ian Rogers#include "jni.h"
21578bbdc684db8ed68e9fedbc678669d27fa68b6eBrian Carlstrom
22761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes#include "base/macros.h"
2376b6167407c2b6f5d40ad895b2793a6b037f54b2Elliott Hughes#include "base/mutex.h"
246c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes#include "indirect_reference_table.h"
2583c8ee000d525017ead8753fce6bc1020249b96aMathieu Chartier#include "object_callbacks.h"
26bbd76717c14822b68ae6d122d88610b46286272fElliott Hughes#include "reference_table.h"
27df20fe0c097073f75f22d16e72fd3636a31d3ca1Ian Rogers
28ae80b493748c5b6ffe310a91c651e7043f4b2daeElliott Hughes#include <iosfwd>
290af5543f8ea20c3e655b2d748a1b7dcf283792feElliott Hughes#include <string>
300af5543f8ea20c3e655b2d748a1b7dcf283792feElliott Hughes
31eac766769e3114a078c188ea26776a81f0edb3cfElliott Hughes#ifndef NATIVE_METHOD
32eac766769e3114a078c188ea26776a81f0edb3cfElliott Hughes#define NATIVE_METHOD(className, functionName, signature) \
33eac766769e3114a078c188ea26776a81f0edb3cfElliott Hughes  { #functionName, signature, reinterpret_cast<void*>(className ## _ ## functionName) }
34eac766769e3114a078c188ea26776a81f0edb3cfElliott Hughes#endif
35eac766769e3114a078c188ea26776a81f0edb3cfElliott Hughes#define REGISTER_NATIVE_METHODS(jni_class_name) \
36eac766769e3114a078c188ea26776a81f0edb3cfElliott Hughes  RegisterNativeMethods(env, jni_class_name, gMethods, arraysize(gMethods))
37eac766769e3114a078c188ea26776a81f0edb3cfElliott Hughes
38df20fe0c097073f75f22d16e72fd3636a31d3ca1Ian Rogersnamespace art {
392dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogersnamespace mirror {
40ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom  class ArtField;
41ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom  class ArtMethod;
42ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom  class ClassLoader;
43ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom}  // namespace mirror
44418d20fc407052d4152157f61e7453359f902383Elliott Hughesunion JValue;
4579082e367845bbd68ec44ef2ddd1be8ef0e1550fElliott Hughesclass Libraries;
46491ca9e75fad381468dd7f5fdbff56d1a9738dd7Brian Carlstromclass ParsedOptions;
47576ca0cd692c0b6ae70e776de91015b8ff000a08Ian Rogersclass Runtime;
4800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogersclass ScopedObjectAccess;
49eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartiertemplate<class T> class Handle;
5018c0753c1659629021b4becdaa3f6ea81aecce35Elliott Hughesclass Thread;
51ea4dca856f8c19299a1858d2cc1f35b03ca0f694Carl Shapiro
5262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogersvoid JniAbortF(const char* jni_function_name, const char* fmt, ...)
5362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    __attribute__((__format__(__printf__, 2, 3)));
5400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogersvoid RegisterNativeMethods(JNIEnv* env, const char* jni_class_name, const JNINativeMethod* methods,
55abd7be989a7509d6dd7325d505fa9926ed502355Ian Rogers                           jint method_count);
56a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
57a4f94740f9d66b21f4bcd3a225c434aa29cfa323Elliott Hughesint ThrowNewException(JNIEnv* env, jclass exception_class, const char* msg, jobject cause);
58a4f94740f9d66b21f4bcd3a225c434aa29cfa323Elliott Hughes
59c11d9b8870de5f860b13c84003ade7b3f3125a52Mathieu Chartierclass JavaVMExt : public JavaVM {
60c11d9b8870de5f860b13c84003ade7b3f3125a52Mathieu Chartier public:
61491ca9e75fad381468dd7f5fdbff56d1a9738dd7Brian Carlstrom  JavaVMExt(Runtime* runtime, ParsedOptions* options);
62de69d7f8c32be83c405bf5a9c5f15fc655f578faElliott Hughes  ~JavaVMExt();
630af5543f8ea20c3e655b2d748a1b7dcf283792feElliott Hughes
647577075b147fd8fa37ca41e7a32d1124676776ceElliott Hughes  /**
657577075b147fd8fa37ca41e7a32d1124676776ceElliott Hughes   * Loads the given shared library. 'path' is an absolute pathname.
660af5543f8ea20c3e655b2d748a1b7dcf283792feElliott Hughes   *
677577075b147fd8fa37ca41e7a32d1124676776ceElliott Hughes   * Returns 'true' on success. On failure, sets 'detail' to a
687577075b147fd8fa37ca41e7a32d1124676776ceElliott Hughes   * human-readable description of the error.
690af5543f8ea20c3e655b2d748a1b7dcf283792feElliott Hughes   */
700cd81352a7c06e381951cea1b104fd73516f4341Mathieu Chartier  bool LoadNativeLibrary(const std::string& path, Handle<mirror::ClassLoader> class_loader,
711eb512d33f94d1dd7ea38263307ba0f7a0dfa653Ian Rogers                         std::string* detail)
72b726dcb581bf72da46527378ccb6889020f0e6e9Ian Rogers      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
73bbd76717c14822b68ae6d122d88610b46286272fElliott Hughes
7479082e367845bbd68ec44ef2ddd1be8ef0e1550fElliott Hughes  /**
7579082e367845bbd68ec44ef2ddd1be8ef0e1550fElliott Hughes   * Returns a pointer to the code for the native method 'm', found
7679082e367845bbd68ec44ef2ddd1be8ef0e1550fElliott Hughes   * using dlsym(3) on every native library that's been loaded so far.
7779082e367845bbd68ec44ef2ddd1be8ef0e1550fElliott Hughes   */
78ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom  void* FindCodeForNativeMethod(mirror::ArtMethod* m)
79b726dcb581bf72da46527378ccb6889020f0e6e9Ian Rogers      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
8079082e367845bbd68ec44ef2ddd1be8ef0e1550fElliott Hughes
81ae80b493748c5b6ffe310a91c651e7043f4b2daeElliott Hughes  void DumpForSigQuit(std::ostream& os);
82ae80b493748c5b6ffe310a91c651e7043f4b2daeElliott Hughes
8300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  void DumpReferenceTables(std::ostream& os)
84b726dcb581bf72da46527378ccb6889020f0e6e9Ian Rogers      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
859d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes
8688c5c355fc3d881f905564911d746b2313d5fc89Elliott Hughes  void SetCheckJniEnabled(bool enabled);
874ffd31315bc0d00ec278e85feed15985de5ac3dcElliott Hughes
8894f7b49578b6aaa80de8ffed230648d601393905Hiroshi Yamauchi  void VisitRoots(RootCallback* callback, void* arg)
8994f7b49578b6aaa80de8ffed230648d601393905Hiroshi Yamauchi      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
90410c0c876f326e14c176a39ba21fc4dd3f7db8abElliott Hughes
91c11d9b8870de5f860b13c84003ade7b3f3125a52Mathieu Chartier  void DisallowNewWeakGlobals() EXCLUSIVE_LOCKS_REQUIRED(Locks::mutator_lock_);
92c11d9b8870de5f860b13c84003ade7b3f3125a52Mathieu Chartier  void AllowNewWeakGlobals() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
93c11d9b8870de5f860b13c84003ade7b3f3125a52Mathieu Chartier  jweak AddWeakGlobalReference(Thread* self, mirror::Object* obj)
94c11d9b8870de5f860b13c84003ade7b3f3125a52Mathieu Chartier    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
95c11d9b8870de5f860b13c84003ade7b3f3125a52Mathieu Chartier  void DeleteWeakGlobalRef(Thread* self, jweak obj)
96c11d9b8870de5f860b13c84003ade7b3f3125a52Mathieu Chartier    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
9794f7b49578b6aaa80de8ffed230648d601393905Hiroshi Yamauchi  void SweepJniWeakGlobals(IsMarkedCallback* callback, void* arg)
9894f7b49578b6aaa80de8ffed230648d601393905Hiroshi Yamauchi      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
99c645f1ddb7c40bea6a38eda4b3f83f6b6dec405bMathieu Chartier  mirror::Object* DecodeWeakGlobal(Thread* self, IndirectRef ref)
100c645f1ddb7c40bea6a38eda4b3f83f6b6dec405bMathieu Chartier      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
101c11d9b8870de5f860b13c84003ade7b3f3125a52Mathieu Chartier
102f2682d5a6ce0f7de58da8fd4ec8aec200c43b92eElliott Hughes  Runtime* runtime;
103bbd76717c14822b68ae6d122d88610b46286272fElliott Hughes
104a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  // Used for testing. By default, we'll LOG(FATAL) the reason.
105b264f081424642b06b0bbe7102781895d41faa9dElliott Hughes  void (*check_jni_abort_hook)(void* data, const std::string& reason);
106b264f081424642b06b0bbe7102781895d41faa9dElliott Hughes  void* check_jni_abort_hook_data;
107a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
108a09576416788b916095739e43a16917e7948f3a4Elliott Hughes  // Extra checking.
109515a5bc89282d6f910cae4d5852bb77124a47825Elliott Hughes  bool check_jni;
110a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  bool force_copy;
111515a5bc89282d6f910cae4d5852bb77124a47825Elliott Hughes
112a09576416788b916095739e43a16917e7948f3a4Elliott Hughes  // Extra diagnostics.
113a09576416788b916095739e43a16917e7948f3a4Elliott Hughes  std::string trace;
114a09576416788b916095739e43a16917e7948f3a4Elliott Hughes
1156c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes  // JNI global references.
116b8a0b94735f188bc739e4c55479c37699006b881Ian Rogers  ReaderWriterMutex globals_lock DEFAULT_MUTEX_ACQUIRED_AFTER;
117c56057e40938c587a74984651a510e320a8cb4fdMathieu Chartier  // Not guarded by globals_lock since we sometimes use SynchronizedGet in Thread::DecodeJObject.
118c56057e40938c587a74984651a510e320a8cb4fdMathieu Chartier  IndirectReferenceTable globals;
1196c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes
12000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  Mutex libraries_lock DEFAULT_MUTEX_ACQUIRED_AFTER;
121f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes  Libraries* libraries GUARDED_BY(libraries_lock);
122a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
123a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  // Used by -Xcheck:jni.
124a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  const JNIInvokeInterface* unchecked_functions;
125c11d9b8870de5f860b13c84003ade7b3f3125a52Mathieu Chartier
126c11d9b8870de5f860b13c84003ade7b3f3125a52Mathieu Chartier private:
127c11d9b8870de5f860b13c84003ade7b3f3125a52Mathieu Chartier  // TODO: Make the other members of this class also private.
128c11d9b8870de5f860b13c84003ade7b3f3125a52Mathieu Chartier  // JNI weak global references.
129c11d9b8870de5f860b13c84003ade7b3f3125a52Mathieu Chartier  Mutex weak_globals_lock_ DEFAULT_MUTEX_ACQUIRED_AFTER;
130196851b634a5bfdd8ab3fb59a320e550b21b0f4dHiroshi Yamauchi  // Since weak_globals_ contain weak roots, be careful not to
131196851b634a5bfdd8ab3fb59a320e550b21b0f4dHiroshi Yamauchi  // directly access the object references in it. Use Get() with the
132196851b634a5bfdd8ab3fb59a320e550b21b0f4dHiroshi Yamauchi  // read barrier enabled.
133c11d9b8870de5f860b13c84003ade7b3f3125a52Mathieu Chartier  IndirectReferenceTable weak_globals_ GUARDED_BY(weak_globals_lock_);
134c11d9b8870de5f860b13c84003ade7b3f3125a52Mathieu Chartier  bool allow_new_weak_globals_ GUARDED_BY(weak_globals_lock_);
135c11d9b8870de5f860b13c84003ade7b3f3125a52Mathieu Chartier  ConditionVariable weak_globals_add_condition_ GUARDED_BY(weak_globals_lock_);
136f2682d5a6ce0f7de58da8fd4ec8aec200c43b92eElliott Hughes};
137f2682d5a6ce0f7de58da8fd4ec8aec200c43b92eElliott Hughes
13869f5bc6759f256a146eefd8a7141d39fcc3b0421Elliott Hughesstruct JNIEnvExt : public JNIEnv {
1397577075b147fd8fa37ca41e7a32d1124676776ceElliott Hughes  JNIEnvExt(Thread* self, JavaVMExt* vm);
140c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes  ~JNIEnvExt();
141bbd76717c14822b68ae6d122d88610b46286272fElliott Hughes
14200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  void DumpReferenceTables(std::ostream& os)
143b726dcb581bf72da46527378ccb6889020f0e6e9Ian Rogers      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
1449d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes
14588c5c355fc3d881f905564911d746b2313d5fc89Elliott Hughes  void SetCheckJniEnabled(bool enabled);
1464ffd31315bc0d00ec278e85feed15985de5ac3dcElliott Hughes
1472ced6a534157d5d963693346904389c19775d2daElliott Hughes  void PushFrame(int capacity);
1482ced6a534157d5d963693346904389c19775d2daElliott Hughes  void PopFrame();
1492ced6a534157d5d963693346904389c19775d2daElliott Hughes
15053b8b09fc80329539585dcf43657bc5f4ecefdffIan Rogers  template<typename T>
151987560fee798e48fb725c44b796d8ca7a5872ad6Ian Rogers  T AddLocalReference(mirror::Object* obj)
15253b8b09fc80329539585dcf43657bc5f4ecefdffIan Rogers      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
15353b8b09fc80329539585dcf43657bc5f4ecefdffIan Rogers
1542dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers  static Offset SegmentStateOffset();
155dc51b79e65abcdad094ccd5e5a2caf5153433d49Ian Rogers
1565a7a74a042e73a355f5cedffa0d2faf5340028faIan Rogers  static Offset LocalRefCookieOffset() {
1575a7a74a042e73a355f5cedffa0d2faf5340028faIan Rogers    return Offset(OFFSETOF_MEMBER(JNIEnvExt, local_ref_cookie));
1585a7a74a042e73a355f5cedffa0d2faf5340028faIan Rogers  }
1595a7a74a042e73a355f5cedffa0d2faf5340028faIan Rogers
160848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers  static Offset SelfOffset() {
161848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers    return Offset(OFFSETOF_MEMBER(JNIEnvExt, self));
162848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers  }
163848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers
164590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier  jobject NewLocalRef(mirror::Object* obj) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
165590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier  void DeleteLocalRef(jobject obj) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
166590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier
16785d1545e985ac689db4bad7849880e843707c862Elliott Hughes  Thread* const self;
1687577075b147fd8fa37ca41e7a32d1124676776ceElliott Hughes  JavaVMExt* vm;
169ea4dca856f8c19299a1858d2cc1f35b03ca0f694Carl Shapiro
1702ced6a534157d5d963693346904389c19775d2daElliott Hughes  // Cookie used when using the local indirect reference table.
1715a7a74a042e73a355f5cedffa0d2faf5340028faIan Rogers  uint32_t local_ref_cookie;
1725a7a74a042e73a355f5cedffa0d2faf5340028faIan Rogers
1735a7a74a042e73a355f5cedffa0d2faf5340028faIan Rogers  // JNI local references.
17435aef2ce9d9cbfb37e9b2f6776afce3caed37063Yevgeny Rouban  IndirectReferenceTable locals GUARDED_BY(Locks::mutator_lock_);
1755a7a74a042e73a355f5cedffa0d2faf5340028faIan Rogers
1762ced6a534157d5d963693346904389c19775d2daElliott Hughes  // Stack of cookies corresponding to PushLocalFrame/PopLocalFrame calls.
1772ced6a534157d5d963693346904389c19775d2daElliott Hughes  // TODO: to avoid leaks (and bugs), we need to clear this vector on entry (or return)
1782ced6a534157d5d963693346904389c19775d2daElliott Hughes  // to a native method.
1792ced6a534157d5d963693346904389c19775d2daElliott Hughes  std::vector<uint32_t> stacked_local_ref_cookies;
1802ced6a534157d5d963693346904389c19775d2daElliott Hughes
181c5bfa8f49d8548d7c685a99b411311ef56bedffaElliott Hughes  // Frequently-accessed fields cached from JavaVM.
182515a5bc89282d6f910cae4d5852bb77124a47825Elliott Hughes  bool check_jni;
183515a5bc89282d6f910cae4d5852bb77124a47825Elliott Hughes
184a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  // How many nested "critical" JNI calls are we in?
185a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  int critical;
186ea4dca856f8c19299a1858d2cc1f35b03ca0f694Carl Shapiro
187bbd76717c14822b68ae6d122d88610b46286272fElliott Hughes  // Entered JNI monitors, for bulk exit on thread detach.
18802b48d1dae0c3adc01ef6668226fb648fb52990aElliott Hughes  ReferenceTable monitors;
1896c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes
190a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  // Used by -Xcheck:jni.
191a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  const JNINativeInterface* unchecked_functions;
192ea4dca856f8c19299a1858d2cc1f35b03ca0f694Carl Shapiro};
193ea4dca856f8c19299a1858d2cc1f35b03ca0f694Carl Shapiro
194a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughesconst JNINativeInterface* GetCheckJniNativeInterface();
195a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughesconst JNIInvokeInterface* GetCheckJniInvokeInterface();
196a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
197dfcdf1a0d2d8d75b4c701317e4a092498a8d1e9eIan Rogers// Used to save and restore the JNIEnvExt state when not going through code created by the JNI
198dfcdf1a0d2d8d75b4c701317e4a092498a8d1e9eIan Rogers// compiler
199dfcdf1a0d2d8d75b4c701317e4a092498a8d1e9eIan Rogersclass ScopedJniEnvLocalRefState {
200dfcdf1a0d2d8d75b4c701317e4a092498a8d1e9eIan Rogers public:
201a51a3dd5603daf3d368b7735067e1d9eb54c4c40Elliott Hughes  explicit ScopedJniEnvLocalRefState(JNIEnvExt* env) : env_(env) {
202dfcdf1a0d2d8d75b4c701317e4a092498a8d1e9eIan Rogers    saved_local_ref_cookie_ = env->local_ref_cookie;
203dfcdf1a0d2d8d75b4c701317e4a092498a8d1e9eIan Rogers    env->local_ref_cookie = env->locals.GetSegmentState();
204dfcdf1a0d2d8d75b4c701317e4a092498a8d1e9eIan Rogers  }
205dfcdf1a0d2d8d75b4c701317e4a092498a8d1e9eIan Rogers
206dfcdf1a0d2d8d75b4c701317e4a092498a8d1e9eIan Rogers  ~ScopedJniEnvLocalRefState() {
207dfcdf1a0d2d8d75b4c701317e4a092498a8d1e9eIan Rogers    env_->locals.SetSegmentState(env_->local_ref_cookie);
208dfcdf1a0d2d8d75b4c701317e4a092498a8d1e9eIan Rogers    env_->local_ref_cookie = saved_local_ref_cookie_;
209dfcdf1a0d2d8d75b4c701317e4a092498a8d1e9eIan Rogers  }
210dfcdf1a0d2d8d75b4c701317e4a092498a8d1e9eIan Rogers
211dfcdf1a0d2d8d75b4c701317e4a092498a8d1e9eIan Rogers private:
212dfcdf1a0d2d8d75b4c701317e4a092498a8d1e9eIan Rogers  JNIEnvExt* env_;
213dfcdf1a0d2d8d75b4c701317e4a092498a8d1e9eIan Rogers  uint32_t saved_local_ref_cookie_;
214dfcdf1a0d2d8d75b4c701317e4a092498a8d1e9eIan Rogers  DISALLOW_COPY_AND_ASSIGN(ScopedJniEnvLocalRefState);
215dfcdf1a0d2d8d75b4c701317e4a092498a8d1e9eIan Rogers};
216dfcdf1a0d2d8d75b4c701317e4a092498a8d1e9eIan Rogers
217df20fe0c097073f75f22d16e72fd3636a31d3ca1Ian Rogers}  // namespace art
218ea4dca856f8c19299a1858d2cc1f35b03ca0f694Carl Shapiro
219b465ab0e103d7760df903c1fddf4fa6b89d5d1f5Elliott Hughesstd::ostream& operator<<(std::ostream& os, const jobjectRefType& rhs);
220fc0e3219edc9a5bf81b166e82fd5db2796eb6a0dBrian Carlstrom#endif  // ART_RUNTIME_JNI_INTERNAL_H_
221