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