11d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light/* 21d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light * Copyright (C) 2016 The Android Open Source Project 31d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light * 41d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light * Licensed under the Apache License, Version 2.0 (the "License"); 51d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light * you may not use this file except in compliance with the License. 61d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light * You may obtain a copy of the License at 71d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light * 81d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light * http://www.apache.org/licenses/LICENSE-2.0 91d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light * 101d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light * Unless required by applicable law or agreed to in writing, software 111d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light * distributed under the License is distributed on an "AS IS" BASIS, 121d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 131d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light * See the License for the specific language governing permissions and 141d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light * limitations under the License. 151d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light */ 161d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light 171d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light#include "1919-vminit-thread-start-timing/vminit.h" 181d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light 195573c37e795668eca81a8488078f798d977685c3Igor Murashkin#include <mutex> 205573c37e795668eca81a8488078f798d977685c3Igor Murashkin#include <thread> 211d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light#include <vector> 221d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light 231d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light#include <jni.h> 241d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light#include <stdio.h> 251d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light#include <string.h> 261d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light#include "android-base/macros.h" 271d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light#include "jvmti.h" 281d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light 291d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light// Test infrastructure 301d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light#include "scoped_local_ref.h" 311d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light#include "jvmti_helper.h" 321d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light#include "jni_helper.h" 331d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light#include "test_env.h" 341d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light 351d8a9741d2979d09a21942fbf9107d212ce2511bAlex Lightnamespace art { 361d8a9741d2979d09a21942fbf9107d212ce2511bAlex Lightnamespace Test1919VMInitThreadStart { 371d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light 381d8a9741d2979d09a21942fbf9107d212ce2511bAlex Lightstruct EventData { 391d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light std::string event; 401d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light jobject data; 411d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light}; 421d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light 431d8a9741d2979d09a21942fbf9107d212ce2511bAlex Lightstruct EventList { 441d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light jrawMonitorID events_mutex; 451d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light std::vector<EventData> events; 461d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light}; 471d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light 481d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light 491d8a9741d2979d09a21942fbf9107d212ce2511bAlex Lightstatic void EnableEvent(jvmtiEnv* env, jvmtiEvent evt) { 501d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light jvmtiError error = env->SetEventNotificationMode(JVMTI_ENABLE, evt, nullptr); 511d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light if (error != JVMTI_ERROR_NONE) { 521d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light printf("Failed to enable event"); 531d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light } 541d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light} 551d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light 561d8a9741d2979d09a21942fbf9107d212ce2511bAlex Lightstatic void JNICALL ThreadStartCallback(jvmtiEnv *jvmti, JNIEnv* env, jthread thread) { 571d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light EventList* list = nullptr; 581d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light CheckJvmtiError(jvmti, jvmti->GetEnvironmentLocalStorage(reinterpret_cast<void**>(&list))); 591d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light CheckJvmtiError(jvmti, jvmti->RawMonitorEnter(list->events_mutex)); 601d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light list->events.push_back({ "ThreadStart", env->NewGlobalRef(thread) }); 611d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light CheckJvmtiError(jvmti, jvmti->RawMonitorExit(list->events_mutex)); 621d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light} 631d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light 641d8a9741d2979d09a21942fbf9107d212ce2511bAlex Lightstatic void JNICALL Test1919AgentThread(jvmtiEnv* jvmti, 651d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light JNIEnv* env, 661d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light void* arg ATTRIBUTE_UNUSED) { 671d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light EventList* list = nullptr; 681d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light CheckJvmtiError(jvmti, jvmti->GetEnvironmentLocalStorage(reinterpret_cast<void**>(&list))); 691d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light CheckJvmtiError(jvmti, jvmti->RawMonitorEnter(list->events_mutex)); 701d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light jthread cur; 711d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light CheckJvmtiError(jvmti, jvmti->GetCurrentThread(&cur)); 721d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light list->events.push_back({ "Test1919AgentThread", env->NewGlobalRef(cur) }); 731d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light env->DeleteLocalRef(cur); 741d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light // Wake up VMInit 751d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light CheckJvmtiError(jvmti, jvmti->RawMonitorNotify(list->events_mutex)); 761d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light CheckJvmtiError(jvmti, jvmti->RawMonitorExit(list->events_mutex)); 771d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light} 781d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light 791d8a9741d2979d09a21942fbf9107d212ce2511bAlex Lightstatic void CreateAgentThread(jvmtiEnv* jvmti, JNIEnv* env) { 801d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light // Create a Thread object. 811d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light ScopedLocalRef<jobject> thread_name(env, env->NewStringUTF("JVMTI_THREAD-Test1919")); 821d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light CHECK(thread_name.get() != nullptr); 831d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light 841d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light ScopedLocalRef<jclass> thread_klass(env, env->FindClass("java/lang/Thread")); 851d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light CHECK(thread_klass.get() != nullptr); 861d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light 871d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light ScopedLocalRef<jobject> thread(env, env->AllocObject(thread_klass.get())); 881d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light CHECK(thread.get() != nullptr); 891d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light 901d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light jmethodID initID = env->GetMethodID(thread_klass.get(), "<init>", "(Ljava/lang/String;)V"); 911d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light CHECK(initID != nullptr); 921d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light 931d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light env->CallNonvirtualVoidMethod(thread.get(), thread_klass.get(), initID, thread_name.get()); 941d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light CHECK(!env->ExceptionCheck()); 951d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light 961d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light // Run agent thread. 971d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light CheckJvmtiError(jvmti, jvmti->RunAgentThread(thread.get(), 981d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light Test1919AgentThread, 991d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light nullptr, 1001d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light JVMTI_THREAD_NORM_PRIORITY)); 1011d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light} 1021d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light 1031d8a9741d2979d09a21942fbf9107d212ce2511bAlex Lightstatic void JNICALL VMInitCallback(jvmtiEnv *jvmti, JNIEnv* env, jthread thread) { 1041d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light EventList* list = nullptr; 1051d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light CheckJvmtiError(jvmti, jvmti->GetEnvironmentLocalStorage(reinterpret_cast<void**>(&list))); 1061d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light CheckJvmtiError(jvmti, jvmti->RawMonitorEnter(list->events_mutex)); 1071d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light list->events.push_back({ "VMInit", env->NewGlobalRef(thread) }); 1081d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light // Create a new thread. 1091d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light CreateAgentThread(jvmti, env); 1101d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light // Wait for new thread to run. 1111d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light CheckJvmtiError(jvmti, jvmti->RawMonitorWait(list->events_mutex, 0)); 1121d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light CheckJvmtiError(jvmti, jvmti->RawMonitorExit(list->events_mutex)); 1131d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light} 1141d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light 1151d8a9741d2979d09a21942fbf9107d212ce2511bAlex Lightstatic void InstallVMEvents(jvmtiEnv* env) { 1161d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light jvmtiEventCallbacks callbacks; 1171d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light memset(&callbacks, 0, sizeof(jvmtiEventCallbacks)); 1181d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light callbacks.VMInit = VMInitCallback; 1191d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light callbacks.ThreadStart = ThreadStartCallback; 1201d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light jvmtiError ret = env->SetEventCallbacks(&callbacks, sizeof(callbacks)); 1211d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light if (ret != JVMTI_ERROR_NONE) { 1221d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light printf("Failed to install callbacks"); 1231d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light } 1241d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light 1251d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light EnableEvent(env, JVMTI_EVENT_VM_INIT); 1261d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light EnableEvent(env, JVMTI_EVENT_THREAD_START); 1271d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light} 1281d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light 1291d8a9741d2979d09a21942fbf9107d212ce2511bAlex Lightstatic void InstallEventList(jvmtiEnv* env) { 1301d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light EventList* list = nullptr; 1311d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light CheckJvmtiError(env, env->Allocate(sizeof(EventList), reinterpret_cast<unsigned char**>(&list))); 1321d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light memset(list, 0, sizeof(EventList)); 1331d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light CheckJvmtiError(env, env->CreateRawMonitor("Test1919 Monitor", &list->events_mutex)); 1341d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light CheckJvmtiError(env, env->SetEnvironmentLocalStorage(list)); 1351d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light} 1361d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light 1371d8a9741d2979d09a21942fbf9107d212ce2511bAlex Lightjint OnLoad(JavaVM* vm, 1381d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light char* options ATTRIBUTE_UNUSED, 1391d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light void* reserved ATTRIBUTE_UNUSED) { 1401d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light if (vm->GetEnv(reinterpret_cast<void**>(&jvmti_env), JVMTI_VERSION_1_0) != 0) { 1411d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light printf("Unable to get jvmti env!\n"); 1421d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light return 1; 1431d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light } 1441d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light InstallVMEvents(jvmti_env); 1451d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light InstallEventList(jvmti_env); 1461d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light return 0; 1471d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light} 1481d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light 1491d8a9741d2979d09a21942fbf9107d212ce2511bAlex Lightextern "C" JNIEXPORT jobjectArray JNICALL Java_art_Test1919_getEventNames(JNIEnv* env, jclass) { 1501d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light EventList* list = nullptr; 1511d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light if (JvmtiErrorToException(env, 1521d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light jvmti_env, 1531d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light jvmti_env->GetEnvironmentLocalStorage( 1541d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light reinterpret_cast<void**>(&list)))) { 1551d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light return nullptr; 1561d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light } 1571d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light if (JvmtiErrorToException(env, jvmti_env, jvmti_env->RawMonitorEnter(list->events_mutex))) { 1581d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light return nullptr; 1591d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light } 1601d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light jobjectArray ret = CreateObjectArray(env, list->events.size(), "java/lang/String", 1611d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light [&](jint i) { 1621d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light return env->NewStringUTF(list->events[i].event.c_str()); 1631d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light }); 1641d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light if (JvmtiErrorToException(env, jvmti_env, jvmti_env->RawMonitorExit(list->events_mutex))) { 1651d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light return nullptr; 1661d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light } 1671d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light return ret; 1681d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light} 1691d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light 1701d8a9741d2979d09a21942fbf9107d212ce2511bAlex Lightextern "C" JNIEXPORT jobjectArray JNICALL Java_art_Test1919_getEventThreads(JNIEnv* env, jclass) { 1711d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light EventList* list = nullptr; 1721d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light if (JvmtiErrorToException(env, 1731d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light jvmti_env, 1741d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light jvmti_env->GetEnvironmentLocalStorage( 1751d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light reinterpret_cast<void**>(&list)))) { 1761d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light return nullptr; 1771d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light } 1781d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light if (JvmtiErrorToException(env, jvmti_env, jvmti_env->RawMonitorEnter(list->events_mutex))) { 1791d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light return nullptr; 1801d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light } 1811d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light jobjectArray ret = CreateObjectArray(env, list->events.size(), "java/lang/Thread", 1821d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light [&](jint i) { 1831d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light return env->NewLocalRef(list->events[i].data); 1841d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light }); 1851d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light if (JvmtiErrorToException(env, jvmti_env, jvmti_env->RawMonitorExit(list->events_mutex))) { 1861d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light return nullptr; 1871d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light } 1881d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light return ret; 1891d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light} 1901d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light 1911d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light} // namespace Test1919VMInitThreadStart 1921d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light} // namespace art 193