blob: 8035361a5e68c8596f7218537a6a7639d314c03f [file] [log] [blame]
#include "jniBleakHelper.h"
#include <cstring>
using namespace std;
jvmtiEnv *jvmti;
JNIEXPORT void JNICALL Java_com_android_tools_idea_bleak_JniBleakHelper_pauseThreads0(JNIEnv *env, jobject self, jstring testThreadNameStr) {
jint nthreads;
jthread *threads;
jvmti->GetAllThreads(&nthreads, &threads);
const char* testThreadName = env->GetStringUTFChars(testThreadNameStr, NULL);
jsize threadNameLength = env->GetStringUTFLength(testThreadNameStr);
for (int i=0; i < nthreads; i++) {
jvmtiThreadInfo info;
jvmti->GetThreadInfo(threads[i], &info);
if (strncmp(testThreadName, info.name, threadNameLength)) { // if it's not the test thread, suspend it
jvmti->SuspendThread(threads[i]);
}
}
env->ReleaseStringUTFChars(testThreadNameStr, testThreadName);
}
JNIEXPORT void JNICALL Java_com_android_tools_idea_bleak_JniBleakHelper_resumeThreads0(JNIEnv *env, jobject self, jstring testThreadNameStr) {
jint nthreads;
jthread *threads;
jvmti->GetAllThreads(&nthreads, &threads);
const char* testThreadName = env->GetStringUTFChars(testThreadNameStr, NULL);
jsize threadNameLength = env->GetStringUTFLength(testThreadNameStr);
for (int i=0; i < nthreads; i++) {
jvmtiThreadInfo info;
jvmti->GetThreadInfo(threads[i], &info);
if (strncmp(testThreadName, info.name, threadNameLength)) { // if it's not the test thread, resume it
jvmti->ResumeThread(threads[i]);
}
}
env->ReleaseStringUTFChars(testThreadNameStr, testThreadName);
}
const jlong GC_ROOT_TAG = 1;
jvmtiIterationControl JNICALL heapRootCallback(jvmtiHeapRootKind root_kind, jlong class_tag, jlong size, jlong *tag_ptr, void *user_data) {
*tag_ptr = GC_ROOT_TAG;
return JVMTI_ITERATION_IGNORE;
}
JNIEXPORT jobjectArray JNICALL Java_com_android_tools_idea_bleak_JniBleakHelper_gcRoots(JNIEnv *env) {
jvmti->IterateOverReachableObjects(heapRootCallback, NULL, NULL, NULL);
jint nroots;
jobject *roots;
jvmti->GetObjectsWithTags(1, &GC_ROOT_TAG, &nroots, &roots, NULL);
jclass objectClass = env->FindClass("java/lang/Object");
jobjectArray arr = env->NewObjectArray(nroots, objectClass, NULL);
for (int i=0; i < nroots; i++) {
env->SetObjectArrayElement(arr, i, roots[i]);
}
return arr;
}
JNIEXPORT jobjectArray JNICALL Java_com_android_tools_idea_bleak_JniBleakHelper_allLoadedClasses0(JNIEnv *env) {
jint nclasses;
jclass *classes;
jvmti->GetLoadedClasses(&nclasses, &classes);
jclass objectClass = env->FindClass("java/lang/Object");
jobjectArray arr = env->NewObjectArray(nclasses, objectClass, NULL);
for (int i=0; i < nclasses; i++) {
env->SetObjectArrayElement(arr, i, classes[i]);
}
return arr;
}
JNIEXPORT jint JNICALL Agent_OnLoad(JavaVM *vm, char *options, void *reserved) {
vm->GetEnv((void **) &jvmti, JVMTI_VERSION_1_0);
jvmtiCapabilities capa;
jvmti->GetCapabilities(&capa);
capa.can_signal_thread = 1;
capa.can_tag_objects = 1;
jvmtiError err = jvmti->AddCapabilities(&capa);
if (err != JVMTI_ERROR_NONE) {
printf("Jvmti error setting capabilities: %d\n", err);
}
return 0;
}