| /* |
| * Copyright (C) 2016 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #include "common_helper.h" |
| |
| #include <sstream> |
| #include <string> |
| |
| #include "android-base/stringprintf.h" |
| #include "jni.h" |
| #include "jvmti.h" |
| |
| #include "jvmti_helper.h" |
| #include "ti_macros.h" |
| |
| namespace art { |
| |
| jobject GetJavaField(jvmtiEnv* jvmti, JNIEnv* env, jclass field_klass, jfieldID f) { |
| jint mods = 0; |
| if (JvmtiErrorToException(env, jvmti, jvmti->GetFieldModifiers(field_klass, f, &mods))) { |
| return nullptr; |
| } |
| |
| bool is_static = (mods & kAccStatic) != 0; |
| return env->ToReflectedField(field_klass, f, is_static); |
| } |
| |
| jobject GetJavaMethod(jvmtiEnv* jvmti, JNIEnv* env, jmethodID m) { |
| jint mods = 0; |
| if (JvmtiErrorToException(env, jvmti, jvmti->GetMethodModifiers(m, &mods))) { |
| return nullptr; |
| } |
| |
| bool is_static = (mods & kAccStatic) != 0; |
| jclass method_klass = nullptr; |
| if (JvmtiErrorToException(env, jvmti, jvmti->GetMethodDeclaringClass(m, &method_klass))) { |
| return nullptr; |
| } |
| jobject res = env->ToReflectedMethod(method_klass, m, is_static); |
| env->DeleteLocalRef(method_klass); |
| return res; |
| } |
| |
| jobject GetJavaValueByType(JNIEnv* env, char type, jvalue value) { |
| std::string name; |
| switch (type) { |
| case 'V': |
| return nullptr; |
| case '[': |
| case 'L': |
| return value.l; |
| case 'Z': |
| name = "java/lang/Boolean"; |
| break; |
| case 'B': |
| name = "java/lang/Byte"; |
| break; |
| case 'C': |
| name = "java/lang/Character"; |
| break; |
| case 'S': |
| name = "java/lang/Short"; |
| break; |
| case 'I': |
| name = "java/lang/Integer"; |
| break; |
| case 'J': |
| name = "java/lang/Long"; |
| break; |
| case 'F': |
| name = "java/lang/Float"; |
| break; |
| case 'D': |
| name = "java/lang/Double"; |
| break; |
| default: |
| LOG(FATAL) << "Unable to figure out type!"; |
| UNREACHABLE(); |
| } |
| std::ostringstream oss; |
| oss << "(" << type << ")L" << name << ";"; |
| std::string args = oss.str(); |
| jclass target = env->FindClass(name.c_str()); |
| jmethodID valueOfMethod = env->GetStaticMethodID(target, "valueOf", args.c_str()); |
| |
| CHECK(valueOfMethod != nullptr) << args; |
| jobject res = env->CallStaticObjectMethodA(target, valueOfMethod, &value); |
| env->DeleteLocalRef(target); |
| return res; |
| } |
| |
| jobject GetJavaValue(jvmtiEnv* jvmtienv, JNIEnv* env, jmethodID m, jvalue value) { |
| char *fname, *fsig, *fgen; |
| if (JvmtiErrorToException(env, jvmtienv, jvmtienv->GetMethodName(m, &fname, &fsig, &fgen))) { |
| return nullptr; |
| } |
| std::string type(fsig); |
| type = type.substr(type.find(')') + 1); |
| jvmtienv->Deallocate(reinterpret_cast<unsigned char*>(fsig)); |
| jvmtienv->Deallocate(reinterpret_cast<unsigned char*>(fname)); |
| jvmtienv->Deallocate(reinterpret_cast<unsigned char*>(fgen)); |
| return GetJavaValueByType(env, type[0], value); |
| } |
| |
| } // namespace art |