blob: ab1d8d8cb1404b8ffe5c6884c1dcd4fd80f17037 [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
17#include "iterate_heap.h"
18
19#include <iostream>
20#include <pthread.h>
21#include <stdio.h>
22#include <vector>
23
24#include "base/logging.h"
25#include "jni.h"
26#include "openjdkjvmti/jvmti.h"
27#include "ScopedPrimitiveArray.h"
28#include "ti-agent/common_load.h"
29
30namespace art {
31namespace Test906IterateHeap {
32
33class IterationConfig {
34 public:
35 IterationConfig() {}
36 virtual ~IterationConfig() {}
37
38 virtual jint Handle(jlong class_tag, jlong size, jlong* tag_ptr, jint length) = 0;
39};
40
41static jint JNICALL HeapIterationCallback(jlong class_tag,
42 jlong size,
43 jlong* tag_ptr,
44 jint length,
45 void* user_data) {
46 IterationConfig* config = reinterpret_cast<IterationConfig*>(user_data);
47 return config->Handle(class_tag, size, tag_ptr, length);
48}
49
50static bool Run(jint heap_filter, jclass klass_filter, IterationConfig* config) {
51 jvmtiHeapCallbacks callbacks;
52 memset(&callbacks, 0, sizeof(jvmtiHeapCallbacks));
53 callbacks.heap_iteration_callback = HeapIterationCallback;
54
55 jvmtiError ret = jvmti_env->IterateThroughHeap(heap_filter,
56 klass_filter,
57 &callbacks,
58 config);
59 if (ret != JVMTI_ERROR_NONE) {
60 char* err;
61 jvmti_env->GetErrorName(ret, &err);
62 printf("Failure running IterateThroughHeap: %s\n", err);
63 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
175// Don't do anything
176jint OnLoad(JavaVM* vm,
177 char* options ATTRIBUTE_UNUSED,
178 void* reserved ATTRIBUTE_UNUSED) {
179 if (vm->GetEnv(reinterpret_cast<void**>(&jvmti_env), JVMTI_VERSION_1_0)) {
180 printf("Unable to get jvmti env!\n");
181 return 1;
182 }
183 return 0;
184}
185
186} // namespace Test906IterateHeap
187} // namespace art