1 /* 2 * Copyright (C) 2016 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 "901-hello-ti-agent/basics.h" 18 19 #include <thread> 20 21 #include <jni.h> 22 #include <stdio.h> 23 #include <string.h> 24 #include "android-base/macros.h" 25 #include "jvmti.h" 26 27 // Test infrastructure 28 #include "jvmti_helper.h" 29 #include "test_env.h" 30 31 namespace art { 32 namespace Test901HelloTi { 33 34 static void EnableEvent(jvmtiEnv* env, jvmtiEvent evt) { 35 jvmtiError error = env->SetEventNotificationMode(JVMTI_ENABLE, evt, nullptr); 36 if (error != JVMTI_ERROR_NONE) { 37 printf("Failed to enable event"); 38 } 39 } 40 41 static jvmtiPhase getPhase(jvmtiEnv* jenv) { 42 jvmtiPhase out = static_cast<jvmtiPhase>(-1); 43 jenv->GetPhase(&out); 44 return out; 45 } 46 47 static void JNICALL VMStartCallback(jvmtiEnv *jenv, JNIEnv* jni_env ATTRIBUTE_UNUSED) { 48 printf("VMStart (phase %d)\n", getPhase(jenv)); 49 fsync(1); 50 } 51 52 static void JNICALL VMInitCallback(jvmtiEnv *jvmti_env, 53 JNIEnv* jni_env ATTRIBUTE_UNUSED, 54 jthread thread ATTRIBUTE_UNUSED) { 55 printf("VMInit (phase %d)\n", getPhase(jvmti_env)); 56 fsync(1); 57 } 58 59 static void JNICALL VMDeathCallback(jvmtiEnv *jenv, JNIEnv* jni_env) { 60 printf("VMDeath (phase %d)\n", getPhase(jenv)); 61 fsync(1); 62 jthread cur_thr; 63 CHECK_EQ(jenv->GetCurrentThread(&cur_thr), JVMTI_ERROR_NONE); 64 CHECK(cur_thr != nullptr); 65 jni_env->DeleteLocalRef(cur_thr); 66 } 67 68 69 static void InstallVMEvents(jvmtiEnv* env) { 70 jvmtiEventCallbacks callbacks; 71 memset(&callbacks, 0, sizeof(jvmtiEventCallbacks)); 72 callbacks.VMStart = VMStartCallback; 73 callbacks.VMInit = VMInitCallback; 74 callbacks.VMDeath = VMDeathCallback; 75 jvmtiError ret = env->SetEventCallbacks(&callbacks, sizeof(callbacks)); 76 if (ret != JVMTI_ERROR_NONE) { 77 printf("Failed to install callbacks"); 78 } 79 80 EnableEvent(env, JVMTI_EVENT_VM_START); 81 EnableEvent(env, JVMTI_EVENT_VM_INIT); 82 EnableEvent(env, JVMTI_EVENT_VM_DEATH); 83 } 84 85 jint OnLoad(JavaVM* vm, 86 char* options ATTRIBUTE_UNUSED, 87 void* reserved ATTRIBUTE_UNUSED) { 88 printf("Loaded Agent for test 901-hello-ti-agent\n"); 89 fsync(1); 90 jvmtiEnv* env = nullptr; 91 jvmtiEnv* env2 = nullptr; 92 93 #define CHECK_CALL_SUCCESS(c) \ 94 do { \ 95 if ((c) != JNI_OK) { \ 96 printf("call " #c " did not succeed\n"); \ 97 return -1; \ 98 } \ 99 } while (false) 100 101 CHECK_CALL_SUCCESS(vm->GetEnv(reinterpret_cast<void**>(&env), JVMTI_VERSION_1_0)); 102 CHECK_CALL_SUCCESS(vm->GetEnv(reinterpret_cast<void**>(&env2), JVMTI_VERSION_1_0)); 103 if (env == env2) { 104 printf("GetEnv returned same environment twice!\n"); 105 return -1; 106 } 107 unsigned char* local_data = nullptr; 108 CHECK_CALL_SUCCESS(env->Allocate(8, &local_data)); 109 strcpy(reinterpret_cast<char*>(local_data), "hello!!"); 110 CHECK_CALL_SUCCESS(env->SetEnvironmentLocalStorage(local_data)); 111 unsigned char* get_data = nullptr; 112 CHECK_CALL_SUCCESS(env->GetEnvironmentLocalStorage(reinterpret_cast<void**>(&get_data))); 113 if (get_data != local_data) { 114 printf("Got different data from local storage then what was set!\n"); 115 return -1; 116 } 117 CHECK_CALL_SUCCESS(env2->GetEnvironmentLocalStorage(reinterpret_cast<void**>(&get_data))); 118 if (get_data != nullptr) { 119 printf("env2 did not have nullptr local storage.\n"); 120 return -1; 121 } 122 CHECK_CALL_SUCCESS(env->Deallocate(local_data)); 123 jint version = 0; 124 CHECK_CALL_SUCCESS(env->GetVersionNumber(&version)); 125 if ((version & JVMTI_VERSION_1) != JVMTI_VERSION_1) { 126 printf("Unexpected version number!\n"); 127 return -1; 128 } 129 130 InstallVMEvents(env); 131 InstallVMEvents(env2); 132 133 CHECK_CALL_SUCCESS(env->DisposeEnvironment()); 134 CHECK_CALL_SUCCESS(env2->DisposeEnvironment()); 135 #undef CHECK_CALL_SUCCESS 136 137 if (vm->GetEnv(reinterpret_cast<void**>(&jvmti_env), JVMTI_VERSION_1_0)) { 138 printf("Unable to get jvmti env!\n"); 139 return 1; 140 } 141 SetStandardCapabilities(jvmti_env); 142 143 jvmtiPhase current_phase; 144 jvmtiError phase_result = jvmti_env->GetPhase(¤t_phase); 145 if (phase_result != JVMTI_ERROR_NONE) { 146 printf("Could not get phase"); 147 return 1; 148 } 149 if (current_phase != JVMTI_PHASE_ONLOAD) { 150 printf("Wrong phase"); 151 return 1; 152 } 153 154 InstallVMEvents(jvmti_env); 155 156 return JNI_OK; 157 } 158 159 extern "C" JNIEXPORT void JNICALL Java_art_Test901_setVerboseFlag( 160 JNIEnv* env, jclass Main_klass ATTRIBUTE_UNUSED, jint iflag, jboolean val) { 161 jvmtiVerboseFlag flag = static_cast<jvmtiVerboseFlag>(iflag); 162 jvmtiError result = jvmti_env->SetVerboseFlag(flag, val); 163 JvmtiErrorToException(env, jvmti_env, result); 164 } 165 166 extern "C" JNIEXPORT jboolean JNICALL Java_art_Test901_checkLivePhase( 167 JNIEnv* env, jclass Main_klass ATTRIBUTE_UNUSED) { 168 jvmtiPhase current_phase; 169 jvmtiError phase_result = jvmti_env->GetPhase(¤t_phase); 170 if (JvmtiErrorToException(env, jvmti_env, phase_result)) { 171 return JNI_FALSE; 172 } 173 return (current_phase == JVMTI_PHASE_LIVE) ? JNI_TRUE : JNI_FALSE; 174 } 175 176 static void CallJvmtiFunction(jvmtiEnv* env, jclass klass, jvmtiError* err) { 177 jint n; 178 jmethodID* methods = nullptr; 179 *err = env->GetClassMethods(klass, &n, &methods); 180 } 181 182 extern "C" JNIEXPORT jboolean JNICALL Java_art_Test901_checkUnattached( 183 JNIEnv* env ATTRIBUTE_UNUSED, jclass Main_klass) { 184 jvmtiError res = JVMTI_ERROR_NONE; 185 std::thread t1(CallJvmtiFunction, jvmti_env, Main_klass, &res); 186 t1.join(); 187 return res == JVMTI_ERROR_UNATTACHED_THREAD; 188 } 189 190 extern "C" JNIEXPORT jstring JNICALL Java_art_Test901_getErrorName( 191 JNIEnv* env, jclass Main_klass ATTRIBUTE_UNUSED, jint error) { 192 char* name; 193 jvmtiError res = jvmti_env->GetErrorName(static_cast<jvmtiError>(error), &name); 194 if (JvmtiErrorToException(env, jvmti_env, res)) { 195 return nullptr; 196 } 197 198 jstring ret_string = env->NewStringUTF(name); 199 jvmtiError dealloc = jvmti_env->Deallocate(reinterpret_cast<unsigned char*>(name)); 200 if (JvmtiErrorToException(env, jvmti_env, dealloc)) { 201 return nullptr; 202 } 203 204 return ret_string; 205 } 206 207 } // namespace Test901HelloTi 208 } // namespace art 209