diff options
author | 2016-10-12 19:48:18 +0000 | |
---|---|---|
committer | 2016-10-12 19:48:18 +0000 | |
commit | e8317d90c61dde07c12e404a2bc1fabf584905c1 (patch) | |
tree | 4681c6dcc7cd432e797d69ba94b157105778de0e /test/906-iterate-heap/iterate_heap.cc | |
parent | 33625ed00f1ba234262cde4edd2c1f569853f4ef (diff) | |
parent | e54d992ee75c0924c9a8d4e2f77dacf44c8c651b (diff) |
Merge "ART: Add heap iteration callback"
Diffstat (limited to 'test/906-iterate-heap/iterate_heap.cc')
-rw-r--r-- | test/906-iterate-heap/iterate_heap.cc | 187 |
1 files changed, 187 insertions, 0 deletions
diff --git a/test/906-iterate-heap/iterate_heap.cc b/test/906-iterate-heap/iterate_heap.cc new file mode 100644 index 0000000000..ab1d8d8cb1 --- /dev/null +++ b/test/906-iterate-heap/iterate_heap.cc @@ -0,0 +1,187 @@ +/* + * Copyright (C) 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "iterate_heap.h" + +#include <iostream> +#include <pthread.h> +#include <stdio.h> +#include <vector> + +#include "base/logging.h" +#include "jni.h" +#include "openjdkjvmti/jvmti.h" +#include "ScopedPrimitiveArray.h" +#include "ti-agent/common_load.h" + +namespace art { +namespace Test906IterateHeap { + +class IterationConfig { + public: + IterationConfig() {} + virtual ~IterationConfig() {} + + virtual jint Handle(jlong class_tag, jlong size, jlong* tag_ptr, jint length) = 0; +}; + +static jint JNICALL HeapIterationCallback(jlong class_tag, + jlong size, + jlong* tag_ptr, + jint length, + void* user_data) { + IterationConfig* config = reinterpret_cast<IterationConfig*>(user_data); + return config->Handle(class_tag, size, tag_ptr, length); +} + +static bool Run(jint heap_filter, jclass klass_filter, IterationConfig* config) { + jvmtiHeapCallbacks callbacks; + memset(&callbacks, 0, sizeof(jvmtiHeapCallbacks)); + callbacks.heap_iteration_callback = HeapIterationCallback; + + jvmtiError ret = jvmti_env->IterateThroughHeap(heap_filter, + klass_filter, + &callbacks, + config); + if (ret != JVMTI_ERROR_NONE) { + char* err; + jvmti_env->GetErrorName(ret, &err); + printf("Failure running IterateThroughHeap: %s\n", err); + return false; + } + return true; +} + +extern "C" JNIEXPORT jint JNICALL Java_Main_iterateThroughHeapCount(JNIEnv* env ATTRIBUTE_UNUSED, + jclass klass ATTRIBUTE_UNUSED, + jint heap_filter, + jclass klass_filter, + jint stop_after) { + class CountIterationConfig : public IterationConfig { + public: + CountIterationConfig(jint _counter, jint _stop_after) + : counter(_counter), + stop_after(_stop_after) { + } + + jint Handle(jlong class_tag ATTRIBUTE_UNUSED, + jlong size ATTRIBUTE_UNUSED, + jlong* tag_ptr ATTRIBUTE_UNUSED, + jint length ATTRIBUTE_UNUSED) OVERRIDE { + counter++; + if (counter == stop_after) { + return JVMTI_VISIT_ABORT; + } + return 0; + } + + jint counter; + const jint stop_after; + }; + + CountIterationConfig config(0, stop_after); + Run(heap_filter, klass_filter, &config); + + if (config.counter > config.stop_after) { + printf("Error: more objects visited than signaled."); + } + + return config.counter; +} + + +extern "C" JNIEXPORT jint JNICALL Java_Main_iterateThroughHeapData(JNIEnv* env, + jclass klass ATTRIBUTE_UNUSED, + jint heap_filter, + jclass klass_filter, + jlongArray class_tags, + jlongArray sizes, + jlongArray tags, + jintArray lengths) { + class DataIterationConfig : public IterationConfig { + public: + jint Handle(jlong class_tag, jlong size, jlong* tag_ptr, jint length) OVERRIDE { + class_tags_.push_back(class_tag); + sizes_.push_back(size); + tags_.push_back(*tag_ptr); + lengths_.push_back(length); + + return 0; // Continue. + } + + std::vector<jlong> class_tags_; + std::vector<jlong> sizes_; + std::vector<jlong> tags_; + std::vector<jint> lengths_; + }; + + DataIterationConfig config; + if (!Run(heap_filter, klass_filter, &config)) { + return -1; + } + + ScopedLongArrayRW s_class_tags(env, class_tags); + ScopedLongArrayRW s_sizes(env, sizes); + ScopedLongArrayRW s_tags(env, tags); + ScopedIntArrayRW s_lengths(env, lengths); + + for (size_t i = 0; i != config.class_tags_.size(); ++i) { + s_class_tags[i] = config.class_tags_[i]; + s_sizes[i] = config.sizes_[i]; + s_tags[i] = config.tags_[i]; + s_lengths[i] = config.lengths_[i]; + } + + return static_cast<jint>(config.class_tags_.size()); +} + +extern "C" JNIEXPORT void JNICALL Java_Main_iterateThroughHeapAdd(JNIEnv* env ATTRIBUTE_UNUSED, + jclass klass ATTRIBUTE_UNUSED, + jint heap_filter, + jclass klass_filter) { + class AddIterationConfig : public IterationConfig { + public: + AddIterationConfig() {} + + jint Handle(jlong class_tag ATTRIBUTE_UNUSED, + jlong size ATTRIBUTE_UNUSED, + jlong* tag_ptr, + jint length ATTRIBUTE_UNUSED) OVERRIDE { + jlong current_tag = *tag_ptr; + if (current_tag != 0) { + *tag_ptr = current_tag + 10; + } + return 0; + } + }; + + AddIterationConfig config; + Run(heap_filter, klass_filter, &config); +} + +// Don't do anything +jint OnLoad(JavaVM* vm, + char* options ATTRIBUTE_UNUSED, + void* reserved ATTRIBUTE_UNUSED) { + if (vm->GetEnv(reinterpret_cast<void**>(&jvmti_env), JVMTI_VERSION_1_0)) { + printf("Unable to get jvmti env!\n"); + return 1; + } + return 0; +} + +} // namespace Test906IterateHeap +} // namespace art |