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