src/sizes/retained_size_by_classes.cpp (84 lines of code) (raw):

// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. #include <vector> #include "retained_size_by_classes.h" #include "sizes_tags.h" #include "retained_size_action.h" jint JNICALL visitObject(jlong classTag, jlong size, jlong *tagPtr, jint length, void *userData) { if (*tagPtr == 0) { return JVMTI_ITERATION_CONTINUE; } Tag *tag = tagToPointer(*tagPtr); for (query_size_t i = 0; i < tag->array.getSize(); i++) { const TagInfoArray::TagInfo &info = tag->array[i]; if (isRetained(info.state)) { reinterpret_cast<jlong *>(userData)[info.index] += size; } } return JVMTI_ITERATION_CONTINUE; } jint JNICALL visitObjectForShallowAndRetainedSize(jlong classTag, jlong size, jlong *tagPtr, jint length, void *userData) { if (*tagPtr == 0) { return JVMTI_ITERATION_CONTINUE; } Tag *tag = tagToPointer(*tagPtr); for (query_size_t i = 0; i < tag->array.getSize(); i++) { const TagInfoArray::TagInfo &info = tag->array[i]; auto *arrays = reinterpret_cast<std::pair<jlong *, jlong *> *>(userData); if (isRetained(info.state)) { arrays->second[info.index] += size; } if (isStartObject(info.state)) { arrays->first[info.index] += size; } } return JVMTI_ITERATION_CONTINUE; } RetainedSizeByClassesAction::RetainedSizeByClassesAction(JNIEnv *env, jvmtiEnv *jvmti, jobject object) : RetainedSizeAction(env, jvmti, object) { } jvmtiError RetainedSizeByClassesAction::getRetainedSizeByClasses(jobjectArray classesArray, std::vector<jlong> &result) { jvmtiError err = tagObjectsOfClasses(classesArray); if (!isOk(err)) return err; if (shouldStopExecution()) return MEMORY_AGENT_INTERRUPTED_ERROR; err = tagHeap(); if (!isOk(err)) return err; if (shouldStopExecution()) return MEMORY_AGENT_INTERRUPTED_ERROR; result.resize(env->GetArrayLength(classesArray)); return IterateThroughHeap(JVMTI_HEAP_FILTER_UNTAGGED, nullptr, visitObject, result.data(), "calculate retained sizes"); } jlongArray RetainedSizeByClassesAction::executeOperation(jobjectArray classesArray) { std::vector<jlong> result; jvmtiError err = getRetainedSizeByClasses(classesArray, result); if (!isOk(err)) { handleError(jvmti, err, "Could not estimate retained size by classes"); return env->NewLongArray(0); } return toJavaArray(env, result); } RetainedAndShallowSizeByClassesAction::RetainedAndShallowSizeByClassesAction(JNIEnv *env, jvmtiEnv *jvmti, jobject object) : RetainedSizeAction(env, jvmti, object) { } jvmtiError RetainedAndShallowSizeByClassesAction::getShallowAndRetainedSizeByClasses(jobjectArray classesArray, std::vector<jlong> &shallowSizes, std::vector<jlong> &retainedSizes) { jvmtiError err = tagObjectsOfClasses(classesArray); if (!isOk(err)) return err; if (shouldStopExecution()) return MEMORY_AGENT_INTERRUPTED_ERROR; err = tagHeap(); if (!isOk(err)) return err; if (shouldStopExecution()) return MEMORY_AGENT_INTERRUPTED_ERROR; retainedSizes.resize(env->GetArrayLength(classesArray)); shallowSizes.resize(env->GetArrayLength(classesArray)); std::pair<jlong *, jlong *> arrays = std::make_pair(shallowSizes.data(), retainedSizes.data()); return IterateThroughHeap(JVMTI_HEAP_FILTER_UNTAGGED, nullptr, visitObjectForShallowAndRetainedSize, &arrays, "calculate shallow and retained sizes"); } jobjectArray RetainedAndShallowSizeByClassesAction::executeOperation(jobjectArray classesArray) { std::vector<jlong> shallowSizes; std::vector<jlong> retainedSizes; jvmtiError err = getShallowAndRetainedSizeByClasses(classesArray,shallowSizes, retainedSizes); jclass langObject = env->FindClass("java/lang/Object"); jobjectArray result = env->NewObjectArray(2, langObject, nullptr); env->SetObjectArrayElement(result, 0, toJavaArray(env, shallowSizes)); env->SetObjectArrayElement(result, 1, toJavaArray(env, retainedSizes)); if (!isOk(err)) { handleError(jvmti, err, "Could not estimate retained size by classes"); } return result; }