@@ -128,110 +128,113 @@ namespace {
128128
129129 return JVMTI_VISIT_OBJECTS;
130130 }
131+
132+ jobjectArray getObjectArrayOfSize (JNIEnv *env, size_t size) {
133+ return env->NewObjectArray (static_cast <jsize>(size), env->FindClass (" java/lang/Object" ), nullptr );
134+ }
131135}
132136
133- jobjectArray RetainedSizeViaDominatorTreeAction::executeOperation (jobjectArray objects) {
134- SizesViaDominatorTreeHeapDumpInfo info;
135- jvmtiError err = info.initAndSetTagsForObjects (env, jvmti, objects);
136- if (err != JVMTI_ERROR_NONE) return nullptr ;
137+ template <typename RESULT_TYPE, typename ... ARGS_TYPES>
138+ jvmtiError RetainedSizesAction<RESULT_TYPE, ARGS_TYPES...>::calculateRetainedSizes(jobjectArray objects,
139+ std::vector<jlong> &retainedSizes,
140+ SizesViaDominatorTreeHeapDumpInfo &info) {
141+ jvmtiError err = info.initAndSetTagsForObjects (this ->env , this ->jvmti , objects);
142+ if (!isOk (err)) return err;
137143
138144 // We set a tag for the input array to ignore it during traversal
139- err = jvmti->SetTag (objects, MOCK_REFERRER_TAG);
140- if (err != JVMTI_ERROR_NONE) return nullptr ;
145+ err = this -> jvmti ->SetTag (objects, MOCK_REFERRER_TAG);
146+ if (! isOk (err)) return err ;
141147
142- progressManager.updateProgress (10 , " Traversing heap for the first time..." );
148+ this -> progressManager .updateProgress (10 , " Traversing heap for the first time..." );
143149 logger::resetTimer ();
144- err = FollowReferences (0 , nullptr , nullptr , firstTraversal, &info, " first traversal " );
150+ err = this -> FollowReferences (0 , nullptr , nullptr , firstTraversal, &info);
145151 logger::logPassedTime ();
146- if (err != JVMTI_ERROR_NONE || shouldStopExecution ()) return nullptr ;
152+ if (! isOk ( err) || this -> shouldStopExecution ()) return err ;
147153
148154 logger::resetTimer ();
149- progressManager.updateProgress (60 , " Traversing heap for the second time..." );
150- err = FollowReferences (0 , nullptr , objects, secondTraversal, &info, " second traversal " );
155+ this -> progressManager .updateProgress (60 , " Traversing heap for the second time..." );
156+ err = this -> FollowReferences (0 , nullptr , objects, secondTraversal, &info);
151157 logger::logPassedTime ();
152- if (err != JVMTI_ERROR_NONE || shouldStopExecution ()) return nullptr ;
158+ if (! isOk ( err) || this -> shouldStopExecution ()) return err ;
153159
154- progressManager.updateProgress (80 , " Calculating retained size..." );
160+ this -> progressManager .updateProgress (80 , " Calculating retained size..." );
155161 info.setUpNeighboursForMasterNode ();
156- std::vector<jlong> retained_sizes = calculateRetainedSizes (info.graph , info.sizes );
162+ retainedSizes = calculateRetainedSizesViaDominatorTree (info.graph , info.sizes );
163+
164+ return err;
165+ }
166+
167+ template <typename RESULT_TYPE, typename ... ARGS_TYPES>
168+ RetainedSizesAction<RESULT_TYPE, ARGS_TYPES...>::RetainedSizesAction(JNIEnv *env, jvmtiEnv *jvmti, jobject object) :
169+ MemoryAgentAction<RESULT_TYPE, ARGS_TYPES...>(env, jvmti, object) {
170+
171+ }
172+
173+ jobjectArray RetainedSizesViaDominatorTreeAction::executeOperation (jobjectArray objects) {
174+ SizesViaDominatorTreeHeapDumpInfo info;
175+ std::vector<jlong> retainedSizes;
176+ jvmtiError err = calculateRetainedSizes (objects, retainedSizes, info);
177+ if (!isOk (err) || shouldStopExecution ()) return nullptr ;
157178
158179 progressManager.updateProgress (95 , " Extracting answer..." );
180+ return constructResultObject (objects, retainedSizes, info);
181+ }
182+
183+ jobjectArray RetainedSizesViaDominatorTreeAction::constructResultObject (jobjectArray objects,
184+ const std::vector<jlong> &retainedSizes,
185+ const SizesViaDominatorTreeHeapDumpInfo &info) {
159186 jsize size = env->GetArrayLength (objects);
160187 std::vector<jlong> shallowSizes;
161- std::vector<jlong> retainedSizes ;
162- retainedSizes .reserve (size);
188+ std::vector<jlong> resultingRetainedSizes ;
189+ resultingRetainedSizes .reserve (size);
163190 shallowSizes.reserve (size);
164191 for (jsize i = 0 ; i < size; i++) {
165192 jobject object = env->GetObjectArrayElement (objects, i);
166193 jlong tag;
167194 jvmti->GetTag (object, &tag);
168- retainedSizes .push_back (retained_sizes [tag]);
195+ resultingRetainedSizes .push_back (retainedSizes [tag]);
169196 shallowSizes.push_back (info.sizes [tag]);
170197 }
171-
172- jclass langObject = env->FindClass (" java/lang/Object" );
173- jobjectArray result = env->NewObjectArray (2 , langObject, nullptr );
198+ jobjectArray result = getObjectArrayOfSize (env, 2 );
174199 env->SetObjectArrayElement (result, 0 , toJavaArray (env, shallowSizes));
175- env->SetObjectArrayElement (result, 1 , toJavaArray (env, retainedSizes));
176- if (!isOk (err)) {
177- handleError (jvmti, err, " Could not estimate retained size by classes" );
178- return nullptr ;
179- }
200+ env->SetObjectArrayElement (result, 1 , toJavaArray (env, resultingRetainedSizes));
201+
180202 return result;
181203}
182204
183- jvmtiError RetainedSizeViaDominatorTreeAction ::cleanHeap () {
205+ jvmtiError RetainedSizesViaDominatorTreeAction ::cleanHeap () {
184206 return removeAllTagsFromHeap (jvmti, nullptr );
185207}
186208
187- RetainedSizeViaDominatorTreeAction::RetainedSizeViaDominatorTreeAction (JNIEnv *env, jvmtiEnv *jvmti, jobject object) :
188- MemoryAgentAction (env, jvmti, object) {
209+ RetainedSizesViaDominatorTreeAction::RetainedSizesViaDominatorTreeAction (JNIEnv *env, jvmtiEnv *jvmti, jobject object) :
210+ RetainedSizesAction (env, jvmti, object) {
189211}
190212
191- jobjectArray RetainedSizeByClassViaDominatorTreeAction ::executeOperation (jobject classRef, jlong objectsLimit) {
213+ jobjectArray RetainedSizesByClassViaDominatorTreeAction ::executeOperation (jobject classRef, jlong objectsLimit) {
192214 jvmtiError err = jvmti->SetTag (classRef, CLASS_TAG);
193- if (err != JVMTI_ERROR_NONE ) return nullptr ;
215+ if (! isOk (err) ) return nullptr ;
194216
195- err = FollowReferences (0 , nullptr , nullptr , collectObjects, nullptr , " collect objects of class" );
196- if (err != JVMTI_ERROR_NONE || shouldStopExecution ()) return nullptr ;
217+ progressManager.updateProgress (5 , " Collecting objects of class" );
218+ err = FollowReferences (0 , nullptr , nullptr , collectObjects, nullptr );
219+ if (!isOk (err) || shouldStopExecution ()) return nullptr ;
197220
198221 std::vector<jobject> objectsOfClass;
199222 err = getObjectsByTags (jvmti, std::vector<jlong>{OBJECT_OF_CLASS_TAG}, objectsOfClass);
200- if (err != JVMTI_ERROR_NONE || shouldStopExecution ()) return nullptr ;
223+ if (! isOk (err) || shouldStopExecution ()) return nullptr ;
201224
202225 // Constructing the master node
203- jclass langObject = env->FindClass (" java/lang/Object" );
204- jobjectArray objects = env->NewObjectArray (objectsOfClass.size (), langObject, nullptr );
226+ jobjectArray objects = getObjectArrayOfSize (env, objectsOfClass.size ());
205227 for (int i = 0 ; i < objectsOfClass.size (); i++) {
206228 env->SetObjectArrayElement (objects, i, objectsOfClass[i]);
207229 }
208230
209231 err = jvmti->SetTag (classRef, 0 );
210- if (err != JVMTI_ERROR_NONE ) return nullptr ;
232+ if (! isOk (err) ) return nullptr ;
211233
212234 SizesViaDominatorTreeHeapDumpInfo info;
213- err = info.initAndSetTagsForObjects (env, jvmti, objects);
214- if (err != JVMTI_ERROR_NONE) return nullptr ;
215-
216- // We set a tag for the input array to ignore it during traversal
217- err = jvmti->SetTag (objects, MOCK_REFERRER_TAG);
218- if (err != JVMTI_ERROR_NONE) return nullptr ;
219-
220- progressManager.updateProgress (10 , " Traversing heap for the first time..." );
221- logger::resetTimer ();
222- err = FollowReferences (0 , nullptr , nullptr , firstTraversal, &info, " first traversal" );
223- logger::logPassedTime ();
224- if (err != JVMTI_ERROR_NONE || shouldStopExecution ()) return nullptr ;
225-
226- logger::resetTimer ();
227- progressManager.updateProgress (60 , " Traversing heap for the second time..." );
228- err = FollowReferences (0 , nullptr , objects, secondTraversal, &info, " second traversal" );
229- logger::logPassedTime ();
230- if (err != JVMTI_ERROR_NONE || shouldStopExecution ()) return nullptr ;
231-
232- progressManager.updateProgress (80 , " Calculating retained size..." );
233- info.setUpNeighboursForMasterNode ();
234- std::vector<jlong> retainedSizes = calculateRetainedSizes (info.graph , info.sizes );
235+ std::vector<jlong> retainedSizes;
236+ err = calculateRetainedSizes (objects, retainedSizes, info);
237+ if (!isOk (err) || shouldStopExecution ()) return nullptr ;
235238
236239 // Sort objects by their retained size
237240 std::sort (objectsOfClass.begin (), objectsOfClass.end (), [&](jobject a, jobject b) {
@@ -243,7 +246,14 @@ jobjectArray RetainedSizeByClassViaDominatorTreeAction::executeOperation(jobject
243246 });
244247
245248 progressManager.updateProgress (95 , " Extracting answer..." );
246- size_t size = std::min ((size_t )objectsLimit, objectsOfClass.size ());
249+ return constructResultObject (objectsOfClass, retainedSizes, info, objectsLimit);
250+ }
251+
252+ jobjectArray RetainedSizesByClassViaDominatorTreeAction::constructResultObject (const std::vector<jobject> &objectsOfClass,
253+ const std::vector<jlong> &retainedSizes,
254+ const SizesViaDominatorTreeHeapDumpInfo &info,
255+ jlong objectsLimit) {
256+ size_t size = std::min (static_cast <size_t >(objectsLimit), objectsOfClass.size ());
247257 std::vector<jlong> shallowSizes;
248258 std::vector<jlong> sortedRetainedSizes;
249259 sortedRetainedSizes.reserve (size);
@@ -256,25 +266,22 @@ jobjectArray RetainedSizeByClassViaDominatorTreeAction::executeOperation(jobject
256266 shallowSizes.push_back (info.sizes [tag]);
257267 }
258268
259- jobjectArray result = env-> NewObjectArray ( 3 , langObject, nullptr );
260- objects = env-> NewObjectArray (size, langObject, nullptr );
269+ jobjectArray result = getObjectArrayOfSize (env, 3 );
270+ jobjectArray objects = getObjectArrayOfSize (env, size );
261271 for (int i = 0 ; i < size; i++) {
262272 env->SetObjectArrayElement (objects, i, objectsOfClass[i]);
263273 }
264274 env->SetObjectArrayElement (result, 0 , objects);
265275 env->SetObjectArrayElement (result, 1 , toJavaArray (env, shallowSizes));
266276 env->SetObjectArrayElement (result, 2 , toJavaArray (env, sortedRetainedSizes));
267- if (!isOk (err)) {
268- handleError (jvmti, err, " Could not estimate retained size by classes" );
269- return nullptr ;
270- }
277+
271278 return result;
272279}
273280
274- jvmtiError RetainedSizeByClassViaDominatorTreeAction ::cleanHeap () {
281+ jvmtiError RetainedSizesByClassViaDominatorTreeAction ::cleanHeap () {
275282 return removeAllTagsFromHeap (jvmti, nullptr );
276283}
277284
278- RetainedSizeByClassViaDominatorTreeAction::RetainedSizeByClassViaDominatorTreeAction (JNIEnv *env, jvmtiEnv *jvmti, jobject object) :
279- MemoryAgentAction (env, jvmti, object) {
285+ RetainedSizesByClassViaDominatorTreeAction::RetainedSizesByClassViaDominatorTreeAction (JNIEnv *env, jvmtiEnv *jvmti, jobject object) :
286+ RetainedSizesAction (env, jvmti, object) {
280287}
0 commit comments