ART: Add primitive field reporting
Add support for primitive_field_callback.
Bug: 31385354
Test: m test-art-host-run-test-906-iterate-heap
Test: m test-art-host-run-test-913-heaps
Change-Id: I4a700813ae11cc3ab49fd5738e0a2cce8a0002ba
diff --git a/test/906-iterate-heap/iterate_heap.cc b/test/906-iterate-heap/iterate_heap.cc
index 890220e..13c3562 100644
--- a/test/906-iterate-heap/iterate_heap.cc
+++ b/test/906-iterate-heap/iterate_heap.cc
@@ -322,5 +322,92 @@
return env->NewStringUTF(fac.data.c_str());
}
+static constexpr const char* GetPrimitiveTypeName(jvmtiPrimitiveType type) {
+ switch (type) {
+ case JVMTI_PRIMITIVE_TYPE_BOOLEAN:
+ return "boolean";
+ case JVMTI_PRIMITIVE_TYPE_BYTE:
+ return "byte";
+ case JVMTI_PRIMITIVE_TYPE_CHAR:
+ return "char";
+ case JVMTI_PRIMITIVE_TYPE_SHORT:
+ return "short";
+ case JVMTI_PRIMITIVE_TYPE_INT:
+ return "int";
+ case JVMTI_PRIMITIVE_TYPE_FLOAT:
+ return "float";
+ case JVMTI_PRIMITIVE_TYPE_LONG:
+ return "long";
+ case JVMTI_PRIMITIVE_TYPE_DOUBLE:
+ return "double";
+ }
+ LOG(FATAL) << "Unknown type " << static_cast<size_t>(type);
+ UNREACHABLE();
+}
+
+extern "C" JNIEXPORT jstring JNICALL Java_Main_iterateThroughHeapPrimitiveFields(
+ JNIEnv* env, jclass klass ATTRIBUTE_UNUSED, jlong tag) {
+ struct FindFieldCallbacks {
+ explicit FindFieldCallbacks(jlong t) : tag_to_find(t) {}
+
+ static jint JNICALL HeapIterationCallback(jlong class_tag ATTRIBUTE_UNUSED,
+ jlong size ATTRIBUTE_UNUSED,
+ jlong* tag_ptr ATTRIBUTE_UNUSED,
+ jint length ATTRIBUTE_UNUSED,
+ void* user_data ATTRIBUTE_UNUSED) {
+ return 0;
+ }
+
+ static jint JNICALL PrimitiveFieldValueCallback(jvmtiHeapReferenceKind kind,
+ const jvmtiHeapReferenceInfo* info,
+ jlong class_tag,
+ jlong* tag_ptr,
+ jvalue value,
+ jvmtiPrimitiveType value_type,
+ void* user_data) {
+ FindFieldCallbacks* p = reinterpret_cast<FindFieldCallbacks*>(user_data);
+ if (*tag_ptr >= p->tag_to_find) {
+ std::ostringstream oss;
+ oss << *tag_ptr
+ << '@'
+ << class_tag
+ << " ("
+ << (kind == JVMTI_HEAP_REFERENCE_FIELD ? "instance, " : "static, ")
+ << GetPrimitiveTypeName(value_type)
+ << ", index="
+ << info->field.index
+ << ") ";
+ // Be lazy, always print eight bytes.
+ static_assert(sizeof(jvalue) == sizeof(uint64_t), "Unexpected jvalue size");
+ uint64_t val;
+ memcpy(&val, &value, sizeof(uint64_t)); // To avoid undefined behavior.
+ oss << android::base::StringPrintf("%016" PRIx64, val);
+
+ if (!p->data.empty()) {
+ p->data += "\n";
+ }
+ p->data += oss.str();
+ *tag_ptr = *tag_ptr + 1;
+ }
+ return 0;
+ }
+
+ std::string data;
+ const jlong tag_to_find;
+ };
+
+ jvmtiHeapCallbacks callbacks;
+ memset(&callbacks, 0, sizeof(jvmtiHeapCallbacks));
+ callbacks.heap_iteration_callback = FindFieldCallbacks::HeapIterationCallback;
+ callbacks.primitive_field_callback = FindFieldCallbacks::PrimitiveFieldValueCallback;
+
+ FindFieldCallbacks ffc(tag);
+ jvmtiError ret = jvmti_env->IterateThroughHeap(0, nullptr, &callbacks, &ffc);
+ if (JvmtiErrorToException(env, ret)) {
+ return nullptr;
+ }
+ return env->NewStringUTF(ffc.data.c_str());
+}
+
} // namespace Test906IterateHeap
} // namespace art