// Copyright 2011 Google Inc. All Rights Reserved. #ifndef ART_SRC_JNI_INTERNAL_H_ #define ART_SRC_JNI_INTERNAL_H_ #include "jni.h" #include "heap.h" #include "indirect_reference_table.h" #include "macros.h" #include "mutex.h" #include "reference_table.h" #include "runtime.h" #include namespace art { class ClassLoader; class Field; union JValue; class Libraries; class Method; class Thread; void SetJniGlobalsMax(size_t max); void JniAbort(const char* jni_function_name); void* FindNativeMethod(Thread* thread); template T Decode(JNIEnv*, jobject); template T AddLocalReference(JNIEnv*, const Object*); inline Field* DecodeField(jfieldID fid) { #ifdef MOVING_GARBAGE_COLLECTOR // TODO: we should make these unique weak globals if Field instances can ever move. UNIMPLEMENTED(WARNING); #endif return reinterpret_cast(fid); } inline jfieldID EncodeField(Field* field) { #ifdef MOVING_GARBAGE_COLLECTOR UNIMPLEMENTED(WARNING); #endif return reinterpret_cast(field); } inline Method* DecodeMethod(jmethodID mid) { #ifdef MOVING_GARBAGE_COLLECTOR // TODO: we should make these unique weak globals if Method instances can ever move. UNIMPLEMENTED(WARNING); #endif return reinterpret_cast(mid); } inline jmethodID EncodeMethod(Method* method) { #ifdef MOVING_GARBAGE_COLLECTOR UNIMPLEMENTED(WARNING); #endif return reinterpret_cast(method); } JValue InvokeWithJValues(JNIEnv* env, jobject obj, jmethodID mid, jvalue* args); struct JavaVMExt : public JavaVM { JavaVMExt(Runtime* runtime, Runtime::ParsedOptions* options); ~JavaVMExt(); /** * Loads the given shared library. 'path' is an absolute pathname. * * Returns 'true' on success. On failure, sets 'detail' to a * human-readable description of the error. */ bool LoadNativeLibrary(const std::string& path, ClassLoader* class_loader, std::string& detail); /** * Returns a pointer to the code for the native method 'm', found * using dlsym(3) on every native library that's been loaded so far. */ void* FindCodeForNativeMethod(Method* m); void DumpReferenceTables(); void EnableCheckJni(); void VisitRoots(Heap::RootVisitor*, void*); Runtime* runtime; // Used for testing. By default, we'll LOG(FATAL) the reason. void (*check_jni_abort_hook)(const std::string& reason); // Extra checking. bool check_jni; bool force_copy; // Extra diagnostics. bool verbose_jni; bool log_third_party_jni; std::string trace; // Used to provide compatibility for apps that assumed direct references. bool work_around_app_jni_bugs; // Used to hold references to pinned primitive arrays. Mutex pins_lock; ReferenceTable pin_table; // JNI global references. Mutex globals_lock; IndirectReferenceTable globals; // JNI weak global references. Mutex weak_globals_lock; IndirectReferenceTable weak_globals; Mutex libraries_lock; Libraries* libraries; // Used by -Xcheck:jni. const JNIInvokeInterface* unchecked_functions; }; struct JNIEnvExt : public JNIEnv { JNIEnvExt(Thread* self, JavaVMExt* vm); ~JNIEnvExt(); void DumpReferenceTables(); void EnableCheckJni(); void PushFrame(int capacity); void PopFrame(); static Offset SegmentStateOffset() { return Offset(OFFSETOF_MEMBER(JNIEnvExt, locals) + IndirectReferenceTable::SegmentStateOffset().Int32Value()); } static Offset LocalRefCookieOffset() { return Offset(OFFSETOF_MEMBER(JNIEnvExt, local_ref_cookie)); } Thread* const self; JavaVMExt* vm; // Cookie used when using the local indirect reference table. uint32_t local_ref_cookie; // JNI local references. IndirectReferenceTable locals; // Stack of cookies corresponding to PushLocalFrame/PopLocalFrame calls. // TODO: to avoid leaks (and bugs), we need to clear this vector on entry (or return) // to a native method. std::vector stacked_local_ref_cookies; // Frequently-accessed fields cached from JavaVM. bool check_jni; bool work_around_app_jni_bugs; // How many nested "critical" JNI calls are we in? int critical; // Entered JNI monitors, for bulk exit on thread detach. ReferenceTable monitors; // Used by -Xcheck:jni. const JNINativeInterface* unchecked_functions; }; const JNINativeInterface* GetCheckJniNativeInterface(); const JNIInvokeInterface* GetCheckJniInvokeInterface(); // Used to save and restore the JNIEnvExt state when not going through code created by the JNI // compiler class ScopedJniEnvLocalRefState { public: explicit ScopedJniEnvLocalRefState(JNIEnvExt* env) : env_(env) { saved_local_ref_cookie_ = env->local_ref_cookie; env->local_ref_cookie = env->locals.GetSegmentState(); } ~ScopedJniEnvLocalRefState() { env_->locals.SetSegmentState(env_->local_ref_cookie); env_->local_ref_cookie = saved_local_ref_cookie_; } private: JNIEnvExt* env_; uint32_t saved_local_ref_cookie_; DISALLOW_COPY_AND_ASSIGN(ScopedJniEnvLocalRefState); }; } // namespace art std::ostream& operator<<(std::ostream& os, const jobjectRefType& rhs); #endif // ART_SRC_JNI_INTERNAL_H_