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 <pthread.h>
18
19 #include <cstdio>
20 #include <iostream>
21 #include <mutex>
22 #include <vector>
23
24 #include "android-base/logging.h"
25 #include "jni.h"
26 #include "jvmti.h"
27 #include "scoped_local_ref.h"
28 #include "scoped_utf_chars.h"
29
30 // Test infrastructure
31 #include "jvmti_helper.h"
32 #include "test_env.h"
33
34 namespace art {
35 namespace Test905ObjectFree {
36
37 // The ObjectFree functions aren't required to be called on any particular thread so use these
38 // mutexs to control access to the collected_tags lists.
39 std::mutex ct1_mutex;
40 static std::vector<jlong> collected_tags1;
41 std::mutex ct2_mutex;
42 static std::vector<jlong> collected_tags2;
43
44 jvmtiEnv* jvmti_env2;
45
ObjectFree1(jvmtiEnv * ti_env,jlong tag)46 static void JNICALL ObjectFree1(jvmtiEnv* ti_env, jlong tag) {
47 std::lock_guard<std::mutex> mu(ct1_mutex);
48 CHECK_EQ(ti_env, jvmti_env);
49 collected_tags1.push_back(tag);
50 }
51
ObjectFree2(jvmtiEnv * ti_env,jlong tag)52 static void JNICALL ObjectFree2(jvmtiEnv* ti_env, jlong tag) {
53 std::lock_guard<std::mutex> mu(ct2_mutex);
54 CHECK_EQ(ti_env, jvmti_env2);
55 collected_tags2.push_back(tag);
56 }
57
setupObjectFreeCallback(JNIEnv * env,jvmtiEnv * jenv,jvmtiEventObjectFree callback)58 static void setupObjectFreeCallback(JNIEnv* env, jvmtiEnv* jenv, jvmtiEventObjectFree callback) {
59 jvmtiEventCallbacks callbacks;
60 memset(&callbacks, 0, sizeof(jvmtiEventCallbacks));
61 callbacks.ObjectFree = callback;
62 jvmtiError ret = jenv->SetEventCallbacks(&callbacks, sizeof(callbacks));
63 JvmtiErrorToException(env, jenv, ret);
64 }
65
Java_art_Test905_setupObjectFreeCallback(JNIEnv * env,jclass klass ATTRIBUTE_UNUSED)66 extern "C" JNIEXPORT void JNICALL Java_art_Test905_setupObjectFreeCallback(
67 JNIEnv* env, jclass klass ATTRIBUTE_UNUSED) {
68 setupObjectFreeCallback(env, jvmti_env, ObjectFree1);
69 JavaVM* jvm = nullptr;
70 env->GetJavaVM(&jvm);
71 CHECK_EQ(jvm->GetEnv(reinterpret_cast<void**>(&jvmti_env2), JVMTI_VERSION_1_2), 0);
72 SetStandardCapabilities(jvmti_env2);
73 setupObjectFreeCallback(env, jvmti_env2, ObjectFree2);
74 }
75
Java_art_Test905_enableFreeTracking(JNIEnv * env,jclass klass ATTRIBUTE_UNUSED,jboolean enable)76 extern "C" JNIEXPORT void JNICALL Java_art_Test905_enableFreeTracking(
77 JNIEnv* env, jclass klass ATTRIBUTE_UNUSED, jboolean enable) {
78 jvmtiError ret = jvmti_env->SetEventNotificationMode(
79 enable ? JVMTI_ENABLE : JVMTI_DISABLE,
80 JVMTI_EVENT_OBJECT_FREE,
81 nullptr);
82 if (JvmtiErrorToException(env, jvmti_env, ret)) {
83 return;
84 }
85 ret = jvmti_env2->SetEventNotificationMode(
86 enable ? JVMTI_ENABLE : JVMTI_DISABLE,
87 JVMTI_EVENT_OBJECT_FREE,
88 nullptr);
89 JvmtiErrorToException(env, jvmti_env, ret);
90 }
91
Java_art_Test905_getCollectedTags(JNIEnv * env,jclass klass ATTRIBUTE_UNUSED,jint index)92 extern "C" JNIEXPORT jlongArray JNICALL Java_art_Test905_getCollectedTags(
93 JNIEnv* env, jclass klass ATTRIBUTE_UNUSED, jint index) {
94 std::lock_guard<std::mutex> mu((index == 0) ? ct1_mutex : ct2_mutex);
95 std::vector<jlong>& tags = (index == 0) ? collected_tags1 : collected_tags2;
96 jlongArray ret = env->NewLongArray(tags.size());
97 if (ret == nullptr) {
98 return ret;
99 }
100
101 env->SetLongArrayRegion(ret, 0, tags.size(), tags.data());
102 tags.clear();
103
104 return ret;
105 }
106
Java_art_Test905_getTag2(JNIEnv * env,jclass klass ATTRIBUTE_UNUSED,jobject obj)107 extern "C" JNIEXPORT jlong JNICALL Java_art_Test905_getTag2(
108 JNIEnv* env, jclass klass ATTRIBUTE_UNUSED, jobject obj) {
109 jlong tag;
110 jvmtiError ret = jvmti_env2->GetTag(obj, &tag);
111 JvmtiErrorToException(env, jvmti_env, ret);
112 return tag;
113 }
114
Java_art_Test905_setTag2(JNIEnv * env,jclass klass ATTRIBUTE_UNUSED,jobject obj,jlong tag)115 extern "C" JNIEXPORT void JNICALL Java_art_Test905_setTag2(
116 JNIEnv* env, jclass klass ATTRIBUTE_UNUSED, jobject obj, jlong tag) {
117 jvmtiError ret = jvmti_env2->SetTag(obj, tag);
118 JvmtiErrorToException(env, jvmti_env, ret);
119 }
120
121 } // namespace Test905ObjectFree
122 } // namespace art
123