227 const char* arg1 = op->arg(1);
228 if (arg1 != NULL && (strlen(arg1) > 0)) {
229 if (strcmp(arg1, "-all") != 0 && strcmp(arg1, "-live") != 0) {
230 out->print_cr("Invalid argument to dumpheap operation: %s", arg1);
231 return JNI_ERR;
232 }
233 live_objects_only = strcmp(arg1, "-live") == 0;
234 }
235
236 // Request a full GC before heap dump if live_objects_only = true
237 // This helps reduces the amount of unreachable objects in the dump
238 // and makes it easier to browse.
239 HeapDumper dumper(live_objects_only /* request GC */);
240 dumper.dump(op->arg(0), out);
241 }
242 return JNI_OK;
243 }
244
245 // Valid Arguments:
246 // "-live" or "-all"
247 // "parallelThreadNum=<N>"
248 // "<filepath>"
249 static jint process_heap_inspect_options(const char* argline,
250 outputStream* out,
251 HeapInspectArgs* args) {
252 char* save_ptr;
253 char* buf = NEW_C_HEAP_ARRAY(char, strlen(argline)+1, mtInternal);
254 snprintf(buf, strlen(argline)+1, "%s", argline);
255 if (buf == NULL) {
256 return JNI_ERR;
257 }
258 char* arg = strtok_r(buf, ",", &save_ptr);
259 while (arg != NULL) {
260 // "-live" or "-all"
261 if (strcmp(arg, "-live") == 0) {
262 args->_live_object_only = true;
263 } else if (strcmp(arg, "-all") == 0) {
264 args->_live_object_only = false;
265 } else if (strncmp(arg, "parallelThreadNum=", 18) == 0) {
266 char* num_str = &arg[18];
267 uintx num = 0;
268 if (!Arguments::parse_uintx(num_str, &num, 0)) {
269 out->print_cr("Invalid parallel thread number");
270 return JNI_ERR;
271 }
272 args->_parallel_thread_num = num;
273 } else {
274 // must be file path
275 assert(args->_path == NULL, "Must be");
276 char* path = args->_path = NEW_C_HEAP_ARRAY(char, strlen(arg)+1, mtInternal);
277 if (path == NULL) {
278 out->print_cr("Out of internal memory.");
279 return JNI_ERR;
280 }
281 snprintf(path, strlen(arg)+1, "%s", arg);
282 if (path[0] == '\0') {
283 out->print_cr("No dump file specified.");
284 } else {
285 fileStream* fs = new (ResourceObj::C_HEAP, mtInternal) fileStream(path);
286 if (fs == NULL) {
311 // Implementation of "inspectheap" command
312 // See also: ClassHistogramDCmd class
313 //
314 // Input arguments :-
315 // all arguments in op->arg(0);
316 static jint heap_inspection(AttachOperation* op, outputStream* out) {
317 bool live_objects_only = true; // default is true to retain the behavior before this change is made
318 outputStream* os = out; // if path not specified or path is NULL, use out
319 const char* arg0 = op->arg(0);
320 size_t parallel_thread_num = os::processor_count() * 3 / 8; // default is less than half of processors.
321 HeapInspectArgs args;
322 // Parse arguments
323 if (arg0 != NULL) {
324 if (JNI_ERR == parse_cmd_options("heap_inspection", arg0, out, (void*)(&args))) {
325 return JNI_ERR;
326 }
327 live_objects_only = args._live_object_only;
328 os = args._fs == NULL ? out : args._fs;
329 parallel_thread_num = args._parallel_thread_num == 0 ? parallel_thread_num : args._parallel_thread_num;
330 if (parallel_thread_num == 0) {
331 // processor_count() <= 2, disable parallel.
332 parallel_thread_num = 1;
333 }
334 }
335
336 VM_GC_HeapInspection heapop(os, live_objects_only /* request full gc */, parallel_thread_num);
337 VMThread::execute(&heapop);
338 if (args._path != NULL) {
339 out->print_cr("Heap inspection file created: %s", args._path);
340 }
341 return JNI_OK;
342 }
343
344 // Implementation of "setflag" command
345 static jint set_flag(AttachOperation* op, outputStream* out) {
346
347 const char* name = NULL;
348 if ((name = op->arg(0)) == NULL) {
349 out->print_cr("flag name is missing");
350 return JNI_ERR;
351 }
|
227 const char* arg1 = op->arg(1);
228 if (arg1 != NULL && (strlen(arg1) > 0)) {
229 if (strcmp(arg1, "-all") != 0 && strcmp(arg1, "-live") != 0) {
230 out->print_cr("Invalid argument to dumpheap operation: %s", arg1);
231 return JNI_ERR;
232 }
233 live_objects_only = strcmp(arg1, "-live") == 0;
234 }
235
236 // Request a full GC before heap dump if live_objects_only = true
237 // This helps reduces the amount of unreachable objects in the dump
238 // and makes it easier to browse.
239 HeapDumper dumper(live_objects_only /* request GC */);
240 dumper.dump(op->arg(0), out);
241 }
242 return JNI_OK;
243 }
244
245 // Valid Arguments:
246 // "-live" or "-all"
247 // "parallel=<N>"
248 // "<filepath>"
249 static jint process_heap_inspect_options(const char* argline,
250 outputStream* out,
251 HeapInspectArgs* args) {
252 char* save_ptr;
253 char* buf = NEW_C_HEAP_ARRAY(char, strlen(argline)+1, mtInternal);
254 snprintf(buf, strlen(argline)+1, "%s", argline);
255 if (buf == NULL) {
256 return JNI_ERR;
257 }
258 char* arg = strtok_r(buf, ",", &save_ptr);
259 while (arg != NULL) {
260 // "-live" or "-all"
261 if (strcmp(arg, "-live") == 0) {
262 args->_live_object_only = true;
263 } else if (strcmp(arg, "-all") == 0) {
264 args->_live_object_only = false;
265 } else if (strncmp(arg, "parallel=", 9) == 0) {
266 char* num_str = &arg[9];
267 uintx num = 0;
268 if (!Arguments::parse_uintx(num_str, &num, 0)) {
269 out->print_cr("Invalid parallel thread number");
270 return JNI_ERR;
271 }
272 args->_parallel_thread_num = num;
273 } else {
274 // must be file path
275 assert(args->_path == NULL, "Must be");
276 char* path = args->_path = NEW_C_HEAP_ARRAY(char, strlen(arg)+1, mtInternal);
277 if (path == NULL) {
278 out->print_cr("Out of internal memory.");
279 return JNI_ERR;
280 }
281 snprintf(path, strlen(arg)+1, "%s", arg);
282 if (path[0] == '\0') {
283 out->print_cr("No dump file specified.");
284 } else {
285 fileStream* fs = new (ResourceObj::C_HEAP, mtInternal) fileStream(path);
286 if (fs == NULL) {
311 // Implementation of "inspectheap" command
312 // See also: ClassHistogramDCmd class
313 //
314 // Input arguments :-
315 // all arguments in op->arg(0);
316 static jint heap_inspection(AttachOperation* op, outputStream* out) {
317 bool live_objects_only = true; // default is true to retain the behavior before this change is made
318 outputStream* os = out; // if path not specified or path is NULL, use out
319 const char* arg0 = op->arg(0);
320 size_t parallel_thread_num = os::processor_count() * 3 / 8; // default is less than half of processors.
321 HeapInspectArgs args;
322 // Parse arguments
323 if (arg0 != NULL) {
324 if (JNI_ERR == parse_cmd_options("heap_inspection", arg0, out, (void*)(&args))) {
325 return JNI_ERR;
326 }
327 live_objects_only = args._live_object_only;
328 os = args._fs == NULL ? out : args._fs;
329 parallel_thread_num = args._parallel_thread_num == 0 ? parallel_thread_num : args._parallel_thread_num;
330 if (parallel_thread_num == 0) {
331 parallel_thread_num = 1;
332 }
333 }
334
335 VM_GC_HeapInspection heapop(os, live_objects_only /* request full gc */, parallel_thread_num);
336 VMThread::execute(&heapop);
337 if (args._path != NULL) {
338 out->print_cr("Heap inspection file created: %s", args._path);
339 }
340 return JNI_OK;
341 }
342
343 // Implementation of "setflag" command
344 static jint set_flag(AttachOperation* op, outputStream* out) {
345
346 const char* name = NULL;
347 if ((name = op->arg(0)) == NULL) {
348 out->print_cr("flag name is missing");
349 return JNI_ERR;
350 }
|