native_bridge_art_interface.cc revision 6d031046eeb5e9f62b657df0695b752e1d0aa583
1/* 2 * Copyright (C) 2014 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 "native_bridge_art_interface.h" 18 19#include "nativebridge/native_bridge.h" 20 21#include "base/logging.h" 22#include "mirror/art_method-inl.h" 23#include "mirror/class-inl.h" 24#include "scoped_thread_state_change.h" 25 26namespace art { 27 28const char* GetMethodShorty(JNIEnv* env, jmethodID mid) { 29 ScopedObjectAccess soa(env); 30 StackHandleScope<1> scope(soa.Self()); 31 mirror::ArtMethod* m = soa.DecodeMethod(mid); 32 MethodHelper mh(scope.NewHandle(m)); 33 return mh.GetShorty(); 34} 35 36uint32_t GetNativeMethodCount(JNIEnv* env, jclass clazz) { 37 if (clazz == nullptr) 38 return 0; 39 40 ScopedObjectAccess soa(env); 41 mirror::Class* c = soa.Decode<mirror::Class*>(clazz); 42 43 uint32_t native_method_count = 0; 44 for (uint32_t i = 0; i < c->NumDirectMethods(); ++i) { 45 mirror::ArtMethod* m = c->GetDirectMethod(i); 46 if (m->IsNative()) { 47 native_method_count++; 48 } 49 } 50 for (uint32_t i = 0; i < c->NumVirtualMethods(); ++i) { 51 mirror::ArtMethod* m = c->GetVirtualMethod(i); 52 if (m->IsNative()) { 53 native_method_count++; 54 } 55 } 56 return native_method_count; 57} 58 59uint32_t GetNativeMethods(JNIEnv* env, jclass clazz, JNINativeMethod* methods, 60 uint32_t method_count) { 61 if ((clazz == nullptr) || (methods == nullptr)) { 62 return 0; 63 } 64 ScopedObjectAccess soa(env); 65 mirror::Class* c = soa.Decode<mirror::Class*>(clazz); 66 67 uint32_t count = 0; 68 for (uint32_t i = 0; i < c->NumDirectMethods(); ++i) { 69 mirror::ArtMethod* m = c->GetDirectMethod(i); 70 if (m->IsNative()) { 71 if (count < method_count) { 72 methods[count].name = m->GetName(); 73 methods[count].signature = m->GetShorty(); 74 methods[count].fnPtr = const_cast<void*>(m->GetNativeMethod()); 75 count++; 76 } else { 77 LOG(WARNING) << "Output native method array too small. Skipping " << PrettyMethod(m); 78 } 79 } 80 } 81 for (uint32_t i = 0; i < c->NumVirtualMethods(); ++i) { 82 mirror::ArtMethod* m = c->GetVirtualMethod(i); 83 if (m->IsNative()) { 84 if (count < method_count) { 85 methods[count].name = m->GetName(); 86 methods[count].signature = m->GetShorty(); 87 methods[count].fnPtr = const_cast<void*>(m->GetNativeMethod()); 88 count++; 89 } else { 90 LOG(WARNING) << "Output native method array too small. Skipping " << PrettyMethod(m); 91 } 92 } 93 } 94 return count; 95} 96 97// Native bridge library runtime callbacks. They represent the runtime interface to native bridge. 98// 99// The interface is expected to expose the following methods: 100// getMethodShorty(): in the case of native method calling JNI native function CallXXXXMethodY(), 101// native bridge calls back to VM for the shorty of the method so that it can prepare based on 102// host calling convention. 103// getNativeMethodCount() and getNativeMethods(): in case of JNI function UnregisterNatives(), 104// native bridge can call back to get all native methods of specified class so that all 105// corresponding trampolines can be destroyed. 106static android::NativeBridgeRuntimeCallbacks native_bridge_art_callbacks_ { 107 GetMethodShorty, GetNativeMethodCount, GetNativeMethods 108}; 109 110void LoadNativeBridge(std::string& native_bridge_library_filename) { 111 android::LoadNativeBridge(native_bridge_library_filename.c_str(), &native_bridge_art_callbacks_); 112 VLOG(startup) << "Runtime::Setup native bridge library: " 113 << (native_bridge_library_filename.empty() ? "(empty)" : native_bridge_library_filename); 114} 115 116void PreInitializeNativeBridge(std::string dir) { 117 VLOG(startup) << "Runtime::Pre-initialize native bridge"; 118#ifndef __APPLE__ // Mac OS does not support CLONE_NEWNS. 119 if (unshare(CLONE_NEWNS) == -1) { 120 LOG(WARNING) << "Could not create mount namespace."; 121 return; 122 } 123 android::PreInitializeNativeBridge(dir.c_str(), GetInstructionSetString(kRuntimeISA)); 124#endif 125} 126 127void InitializeNativeBridge(JNIEnv* env, const char* instruction_set) { 128 android::InitializeNativeBridge(env, instruction_set); 129} 130 131void UnloadNativeBridge() { 132 android::UnloadNativeBridge(); 133} 134 135}; // namespace art 136