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 Test1900TrackAlloc { 26 27 typedef jvmtiError (*GetGlobalState)(jvmtiEnv* env, jlong* allocated); 28 29 struct AllocTrackingData { 30 GetGlobalState get_global_state; 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 extern "C" JNIEXPORT void JNICALL Java_art_Test1900_doDeallocate(JNIEnv* env, 45 jclass, 46 jlong jvmti_env_ptr, 47 jlong ptr) { 48 JvmtiErrorToException(env, 49 reinterpret_cast<jvmtiEnv*>(jvmti_env_ptr), 50 reinterpret_cast<jvmtiEnv*>(jvmti_env_ptr)->Deallocate( 51 reinterpret_cast<unsigned char*>(static_cast<intptr_t>(ptr)))); 52 } 53 54 extern "C" JNIEXPORT jlong JNICALL Java_art_Test1900_doAllocate(JNIEnv* env, 55 jclass, 56 jlong jvmti_env_ptr, 57 jlong size) { 58 unsigned char* res = nullptr; 59 JvmtiErrorToException(env, 60 reinterpret_cast<jvmtiEnv*>(jvmti_env_ptr), 61 reinterpret_cast<jvmtiEnv*>(jvmti_env_ptr)->Allocate(size, &res)); 62 return static_cast<jlong>(reinterpret_cast<intptr_t>(res)); 63 } 64 65 extern "C" JNIEXPORT jlong JNICALL Java_art_Test1900_getAmountAllocated(JNIEnv* env, jclass) { 66 AllocTrackingData* data = nullptr; 67 if (JvmtiErrorToException( 68 env, jvmti_env, jvmti_env->GetEnvironmentLocalStorage(reinterpret_cast<void**>(&data)))) { 69 return -1; 70 } 71 if (data == nullptr || data->get_global_state == nullptr) { 72 ScopedLocalRef<jclass> rt_exception(env, env->FindClass("java/lang/RuntimeException")); 73 env->ThrowNew(rt_exception.get(), "Alloc tracking data not initialized."); 74 return -1; 75 } 76 jlong allocated = -1; 77 JvmtiErrorToException(env, jvmti_env, data->get_global_state(jvmti_env, &allocated)); 78 return allocated; 79 } 80 81 static void DeallocParams(jvmtiParamInfo* params, jint n_params) { 82 for (jint i = 0; i < n_params; i++) { 83 Dealloc(params[i].name); 84 } 85 } 86 87 extern "C" JNIEXPORT jlong JNICALL Java_art_Test1900_getDefaultJvmtiEnv(JNIEnv*, jclass) { 88 return static_cast<jlong>(reinterpret_cast<intptr_t>(jvmti_env)); 89 } 90 91 extern "C" JNIEXPORT void Java_art_Test1900_destroyJvmtiEnv(JNIEnv* env, 92 jclass, 93 jlong jvmti_env_ptr) { 94 JvmtiErrorToException(env, 95 jvmti_env, 96 reinterpret_cast<jvmtiEnv*>(jvmti_env_ptr)->DisposeEnvironment()); 97 } 98 99 extern "C" JNIEXPORT jlong Java_art_Test1900_newJvmtiEnv(JNIEnv* env, jclass) { 100 JavaVM* vm = nullptr; 101 if (env->GetJavaVM(&vm) != 0) { 102 ScopedLocalRef<jclass> rt_exception(env, env->FindClass("java/lang/RuntimeException")); 103 env->ThrowNew(rt_exception.get(), "Unable to get JavaVM"); 104 return -1; 105 } 106 jvmtiEnv* new_env = nullptr; 107 if (vm->GetEnv(reinterpret_cast<void**>(&new_env), JVMTI_VERSION_1_0) != 0) { 108 ScopedLocalRef<jclass> rt_exception(env, env->FindClass("java/lang/RuntimeException")); 109 env->ThrowNew(rt_exception.get(), "Unable to create new jvmtiEnv"); 110 return -1; 111 } 112 return static_cast<jlong>(reinterpret_cast<intptr_t>(new_env)); 113 } 114 115 extern "C" JNIEXPORT void JNICALL Java_art_Test1900_initializeTest(JNIEnv* env, jclass) { 116 void* old_data = nullptr; 117 if (JvmtiErrorToException(env, jvmti_env, jvmti_env->GetEnvironmentLocalStorage(&old_data))) { 118 return; 119 } else if (old_data != nullptr) { 120 ScopedLocalRef<jclass> rt_exception(env, env->FindClass("java/lang/RuntimeException")); 121 env->ThrowNew(rt_exception.get(), "Environment already has local storage set!"); 122 return; 123 } 124 AllocTrackingData* data = nullptr; 125 if (JvmtiErrorToException(env, 126 jvmti_env, 127 jvmti_env->Allocate(sizeof(AllocTrackingData), 128 reinterpret_cast<unsigned char**>(&data)))) { 129 return; 130 } 131 memset(data, 0, sizeof(AllocTrackingData)); 132 // Get the extensions. 133 jint n_ext = 0; 134 jvmtiExtensionFunctionInfo* infos = nullptr; 135 if (JvmtiErrorToException(env, jvmti_env, jvmti_env->GetExtensionFunctions(&n_ext, &infos))) { 136 return; 137 } 138 for (jint i = 0; i < n_ext; i++) { 139 jvmtiExtensionFunctionInfo* cur_info = &infos[i]; 140 if (strcmp("com.android.art.alloc.get_global_jvmti_allocation_state", cur_info->id) == 0) { 141 data->get_global_state = reinterpret_cast<GetGlobalState>(cur_info->func); 142 } 143 // Cleanup the cur_info 144 DeallocParams(cur_info->params, cur_info->param_count); 145 Dealloc(cur_info->id, cur_info->short_description, cur_info->params, cur_info->errors); 146 } 147 // Cleanup the array. 148 Dealloc(infos); 149 if (data->get_global_state == nullptr) { 150 ScopedLocalRef<jclass> rt_exception(env, env->FindClass("java/lang/RuntimeException")); 151 env->ThrowNew(rt_exception.get(), "Unable to find memory tracking extensions."); 152 return; 153 } 154 JvmtiErrorToException(env, jvmti_env, jvmti_env->SetEnvironmentLocalStorage(data)); 155 return; 156 } 157 158 } // namespace Test1900TrackAlloc 159 } // namespace art 160