blob: 1362d470e6e46321d3f97c3a4e8c9e939a09584a [file] [log] [blame]
Andreas Gampee54d9922016-10-11 19:55:37 -07001/*
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
Andreas Gampee54d9922016-10-11 19:55:37 -070017#include <iostream>
18#include <pthread.h>
19#include <stdio.h>
20#include <vector>
21
22#include "base/logging.h"
23#include "jni.h"
24#include "openjdkjvmti/jvmti.h"
25#include "ScopedPrimitiveArray.h"
Alex Lighte6574242016-08-17 09:56:24 -070026#include "ti-agent/common_helper.h"
Andreas Gampee54d9922016-10-11 19:55:37 -070027#include "ti-agent/common_load.h"
28
29namespace art {
30namespace Test906IterateHeap {
31
32class IterationConfig {
33 public:
34 IterationConfig() {}
35 virtual ~IterationConfig() {}
36
37 virtual jint Handle(jlong class_tag, jlong size, jlong* tag_ptr, jint length) = 0;
38};
39
40static jint JNICALL HeapIterationCallback(jlong class_tag,
41 jlong size,
42 jlong* tag_ptr,
43 jint length,
44 void* user_data) {
45 IterationConfig* config = reinterpret_cast<IterationConfig*>(user_data);
46 return config->Handle(class_tag, size, tag_ptr, length);
47}
48
49static bool Run(jint heap_filter, jclass klass_filter, IterationConfig* config) {
50 jvmtiHeapCallbacks callbacks;
51 memset(&callbacks, 0, sizeof(jvmtiHeapCallbacks));
52 callbacks.heap_iteration_callback = HeapIterationCallback;
53
54 jvmtiError ret = jvmti_env->IterateThroughHeap(heap_filter,
55 klass_filter,
56 &callbacks,
57 config);
58 if (ret != JVMTI_ERROR_NONE) {
59 char* err;
60 jvmti_env->GetErrorName(ret, &err);
61 printf("Failure running IterateThroughHeap: %s\n", err);
Alex Light41960712017-01-06 14:44:23 -080062 jvmti_env->Deallocate(reinterpret_cast<unsigned char*>(err));
Andreas Gampee54d9922016-10-11 19:55:37 -070063 return false;
64 }
65 return true;
66}
67
68extern "C" JNIEXPORT jint JNICALL Java_Main_iterateThroughHeapCount(JNIEnv* env ATTRIBUTE_UNUSED,
69 jclass klass ATTRIBUTE_UNUSED,
70 jint heap_filter,
71 jclass klass_filter,
72 jint stop_after) {
73 class CountIterationConfig : public IterationConfig {
74 public:
75 CountIterationConfig(jint _counter, jint _stop_after)
76 : counter(_counter),
77 stop_after(_stop_after) {
78 }
79
80 jint Handle(jlong class_tag ATTRIBUTE_UNUSED,
81 jlong size ATTRIBUTE_UNUSED,
82 jlong* tag_ptr ATTRIBUTE_UNUSED,
83 jint length ATTRIBUTE_UNUSED) OVERRIDE {
84 counter++;
85 if (counter == stop_after) {
86 return JVMTI_VISIT_ABORT;
87 }
88 return 0;
89 }
90
91 jint counter;
92 const jint stop_after;
93 };
94
95 CountIterationConfig config(0, stop_after);
96 Run(heap_filter, klass_filter, &config);
97
98 if (config.counter > config.stop_after) {
99 printf("Error: more objects visited than signaled.");
100 }
101
102 return config.counter;
103}
104
105
106extern "C" JNIEXPORT jint JNICALL Java_Main_iterateThroughHeapData(JNIEnv* env,
107 jclass klass ATTRIBUTE_UNUSED,
108 jint heap_filter,
109 jclass klass_filter,
110 jlongArray class_tags,
111 jlongArray sizes,
112 jlongArray tags,
113 jintArray lengths) {
114 class DataIterationConfig : public IterationConfig {
115 public:
116 jint Handle(jlong class_tag, jlong size, jlong* tag_ptr, jint length) OVERRIDE {
117 class_tags_.push_back(class_tag);
118 sizes_.push_back(size);
119 tags_.push_back(*tag_ptr);
120 lengths_.push_back(length);
121
122 return 0; // Continue.
123 }
124
125 std::vector<jlong> class_tags_;
126 std::vector<jlong> sizes_;
127 std::vector<jlong> tags_;
128 std::vector<jint> lengths_;
129 };
130
131 DataIterationConfig config;
132 if (!Run(heap_filter, klass_filter, &config)) {
133 return -1;
134 }
135
136 ScopedLongArrayRW s_class_tags(env, class_tags);
137 ScopedLongArrayRW s_sizes(env, sizes);
138 ScopedLongArrayRW s_tags(env, tags);
139 ScopedIntArrayRW s_lengths(env, lengths);
140
141 for (size_t i = 0; i != config.class_tags_.size(); ++i) {
142 s_class_tags[i] = config.class_tags_[i];
143 s_sizes[i] = config.sizes_[i];
144 s_tags[i] = config.tags_[i];
145 s_lengths[i] = config.lengths_[i];
146 }
147
148 return static_cast<jint>(config.class_tags_.size());
149}
150
151extern "C" JNIEXPORT void JNICALL Java_Main_iterateThroughHeapAdd(JNIEnv* env ATTRIBUTE_UNUSED,
152 jclass klass ATTRIBUTE_UNUSED,
153 jint heap_filter,
154 jclass klass_filter) {
155 class AddIterationConfig : public IterationConfig {
156 public:
157 AddIterationConfig() {}
158
159 jint Handle(jlong class_tag ATTRIBUTE_UNUSED,
160 jlong size ATTRIBUTE_UNUSED,
161 jlong* tag_ptr,
162 jint length ATTRIBUTE_UNUSED) OVERRIDE {
163 jlong current_tag = *tag_ptr;
164 if (current_tag != 0) {
165 *tag_ptr = current_tag + 10;
166 }
167 return 0;
168 }
169 };
170
171 AddIterationConfig config;
172 Run(heap_filter, klass_filter, &config);
173}
174
Andreas Gampee54d9922016-10-11 19:55:37 -0700175} // namespace Test906IterateHeap
176} // namespace art