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 using GetDescriptorList = jvmtiError(*)(jvmtiEnv* env, jobject loader, jint* cnt, char*** descs);
28
29 struct DescriptorData {
30 GetDescriptorList get_descriptor_list;
31 };
32
33 template <typename T>
Dealloc(T * t)34 static void Dealloc(T* t) {
35 jvmti_env->Deallocate(reinterpret_cast<unsigned char*>(t));
36 }
37
38 template <typename T, typename ...Rest>
Dealloc(T * t,Rest...rs)39 static void Dealloc(T* t, Rest... rs) {
40 Dealloc(t);
41 Dealloc(rs...);
42 }
43
Cleanup(char ** data,jint cnt)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
Java_art_Test1946_getClassloaderDescriptors(JNIEnv * env,jclass,jobject loader)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
DeallocParams(jvmtiParamInfo * params,jint n_params)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
Java_art_Test1946_initializeTest(JNIEnv * env,jclass)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