1 /* 2 * Copyright (C) 2013 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 "jvmti.h" 18 19 // Test infrastructure 20 #include "jvmti_helper.h" 21 #include "scoped_local_ref.h" 22 #include "test_env.h" 23 24 namespace art { 25 namespace Test1946Descriptors { 26 27 typedef jvmtiError (*GetDescriptorList)(jvmtiEnv* env, jobject loader, jint* cnt, char*** descs); 28 29 struct DescriptorData { 30 GetDescriptorList get_descriptor_list; 31 }; 32 33 template <typename T> 34 static void Dealloc(T* t) { 35 jvmti_env->Deallocate(reinterpret_cast<unsigned char*>(t)); 36 } 37 38 template <typename T, typename ...Rest> 39 static void Dealloc(T* t, Rest... rs) { 40 Dealloc(t); 41 Dealloc(rs...); 42 } 43 44 static void Cleanup(char** data, jint cnt) { 45 for (jint i = 0; i < cnt; i++) { 46 Dealloc(data[i]); 47 } 48 Dealloc(data); 49 } 50 51 extern "C" JNIEXPORT jobjectArray JNICALL Java_art_Test1946_getClassloaderDescriptors( 52 JNIEnv* env, jclass, jobject loader) { 53 DescriptorData* data = nullptr; 54 if (JvmtiErrorToException( 55 env, jvmti_env, jvmti_env->GetEnvironmentLocalStorage(reinterpret_cast<void**>(&data)))) { 56 return nullptr; 57 } 58 if (data == nullptr || data->get_descriptor_list == nullptr) { 59 ScopedLocalRef<jclass> rt_exception(env, env->FindClass("java/lang/RuntimeException")); 60 env->ThrowNew(rt_exception.get(), "Alloc tracking data not initialized."); 61 return nullptr; 62 } 63 char** classes = nullptr; 64 jint cnt = -1; 65 if (JvmtiErrorToException(env, jvmti_env, data->get_descriptor_list(jvmti_env, 66 loader, 67 &cnt, 68 &classes))) { 69 return nullptr; 70 } 71 ScopedLocalRef<jobjectArray> arr(env, env->NewObjectArray(cnt, 72 env->FindClass("java/lang/String"), 73 nullptr)); 74 if (env->ExceptionCheck()) { 75 Cleanup(classes, cnt); 76 return nullptr; 77 } 78 79 for (jint i = 0; i < cnt; i++) { 80 env->SetObjectArrayElement(arr.get(), i, env->NewStringUTF(classes[i])); 81 if (env->ExceptionCheck()) { 82 Cleanup(classes, cnt); 83 return nullptr; 84 } 85 } 86 Cleanup(classes, cnt); 87 return arr.release(); 88 } 89 90 static void DeallocParams(jvmtiParamInfo* params, jint n_params) { 91 for (jint i = 0; i < n_params; i++) { 92 Dealloc(params[i].name); 93 } 94 } 95 96 extern "C" JNIEXPORT void JNICALL Java_art_Test1946_initializeTest(JNIEnv* env, jclass) { 97 void* old_data = nullptr; 98 if (JvmtiErrorToException(env, jvmti_env, jvmti_env->GetEnvironmentLocalStorage(&old_data))) { 99 return; 100 } else if (old_data != nullptr) { 101 ScopedLocalRef<jclass> rt_exception(env, env->FindClass("java/lang/RuntimeException")); 102 env->ThrowNew(rt_exception.get(), "Environment already has local storage set!"); 103 return; 104 } 105 DescriptorData* data = nullptr; 106 if (JvmtiErrorToException(env, 107 jvmti_env, 108 jvmti_env->Allocate(sizeof(DescriptorData), 109 reinterpret_cast<unsigned char**>(&data)))) { 110 return; 111 } 112 memset(data, 0, sizeof(DescriptorData)); 113 // Get the extensions. 114 jint n_ext = 0; 115 jvmtiExtensionFunctionInfo* infos = nullptr; 116 if (JvmtiErrorToException(env, jvmti_env, jvmti_env->GetExtensionFunctions(&n_ext, &infos))) { 117 return; 118 } 119 for (jint i = 0; i < n_ext; i++) { 120 jvmtiExtensionFunctionInfo* cur_info = &infos[i]; 121 if (strcmp("com.android.art.class.get_class_loader_class_descriptors", cur_info->id) == 0) { 122 data->get_descriptor_list = reinterpret_cast<GetDescriptorList>(cur_info->func); 123 } 124 // Cleanup the cur_info 125 DeallocParams(cur_info->params, cur_info->param_count); 126 Dealloc(cur_info->id, cur_info->short_description, cur_info->params, cur_info->errors); 127 } 128 // Cleanup the array. 129 Dealloc(infos); 130 if (data->get_descriptor_list == nullptr) { 131 ScopedLocalRef<jclass> rt_exception(env, env->FindClass("java/lang/RuntimeException")); 132 env->ThrowNew(rt_exception.get(), "Unable to find memory tracking extensions."); 133 return; 134 } 135 JvmtiErrorToException(env, jvmti_env, jvmti_env->SetEnvironmentLocalStorage(data)); 136 return; 137 } 138 139 } // namespace Test1946Descriptors 140 } // namespace art 141