jdk

Форк
0
/
management.cpp 
2317 строк · 81.6 Кб
1
/*
2
 * Copyright (c) 2003, 2024, Oracle and/or its affiliates. All rights reserved.
3
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
 *
5
 * This code is free software; you can redistribute it and/or modify it
6
 * under the terms of the GNU General Public License version 2 only, as
7
 * published by the Free Software Foundation.
8
 *
9
 * This code is distributed in the hope that it will be useful, but WITHOUT
10
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12
 * version 2 for more details (a copy is included in the LICENSE file that
13
 * accompanied this code).
14
 *
15
 * You should have received a copy of the GNU General Public License version
16
 * 2 along with this work; if not, write to the Free Software Foundation,
17
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18
 *
19
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20
 * or visit www.oracle.com if you need additional information or have any
21
 * questions.
22
 *
23
 */
24

25
#include "precompiled.hpp"
26
#include "classfile/classLoader.hpp"
27
#include "classfile/systemDictionary.hpp"
28
#include "classfile/vmClasses.hpp"
29
#include "compiler/compileBroker.hpp"
30
#include "gc/shared/collectedHeap.hpp"
31
#include "jmm.h"
32
#include "memory/allocation.inline.hpp"
33
#include "memory/iterator.hpp"
34
#include "memory/oopFactory.hpp"
35
#include "memory/resourceArea.hpp"
36
#include "memory/universe.hpp"
37
#include "oops/klass.hpp"
38
#include "oops/klass.inline.hpp"
39
#include "oops/objArrayKlass.hpp"
40
#include "oops/objArrayOop.inline.hpp"
41
#include "oops/oop.inline.hpp"
42
#include "oops/oopHandle.inline.hpp"
43
#include "oops/typeArrayOop.inline.hpp"
44
#include "runtime/flags/jvmFlag.hpp"
45
#include "runtime/globals.hpp"
46
#include "runtime/handles.inline.hpp"
47
#include "runtime/interfaceSupport.inline.hpp"
48
#include "runtime/javaCalls.hpp"
49
#include "runtime/jniHandles.inline.hpp"
50
#include "runtime/mutexLocker.hpp"
51
#include "runtime/notificationThread.hpp"
52
#include "runtime/os.hpp"
53
#include "runtime/thread.inline.hpp"
54
#include "runtime/threads.hpp"
55
#include "runtime/threadSMR.hpp"
56
#include "runtime/vmOperations.hpp"
57
#include "services/classLoadingService.hpp"
58
#include "services/diagnosticCommand.hpp"
59
#include "services/diagnosticFramework.hpp"
60
#include "services/finalizerService.hpp"
61
#include "services/writeableFlags.hpp"
62
#include "services/heapDumper.hpp"
63
#include "services/lowMemoryDetector.hpp"
64
#include "services/gcNotifier.hpp"
65
#include "services/management.hpp"
66
#include "services/memoryManager.hpp"
67
#include "services/memoryPool.hpp"
68
#include "services/memoryService.hpp"
69
#include "services/runtimeService.hpp"
70
#include "services/threadService.hpp"
71
#include "utilities/debug.hpp"
72
#include "utilities/formatBuffer.hpp"
73
#include "utilities/macros.hpp"
74

75
PerfVariable* Management::_begin_vm_creation_time = nullptr;
76
PerfVariable* Management::_end_vm_creation_time = nullptr;
77
PerfVariable* Management::_vm_init_done_time = nullptr;
78

79
InstanceKlass* Management::_diagnosticCommandImpl_klass = nullptr;
80
InstanceKlass* Management::_garbageCollectorExtImpl_klass = nullptr;
81
InstanceKlass* Management::_garbageCollectorMXBean_klass = nullptr;
82
InstanceKlass* Management::_gcInfo_klass = nullptr;
83
InstanceKlass* Management::_managementFactoryHelper_klass = nullptr;
84
InstanceKlass* Management::_memoryManagerMXBean_klass = nullptr;
85
InstanceKlass* Management::_memoryPoolMXBean_klass = nullptr;
86
InstanceKlass* Management::_memoryUsage_klass = nullptr;
87
InstanceKlass* Management::_sensor_klass = nullptr;
88
InstanceKlass* Management::_threadInfo_klass = nullptr;
89

90
jmmOptionalSupport Management::_optional_support = {0};
91
TimeStamp Management::_stamp;
92

93
void management_init() {
94
#if INCLUDE_MANAGEMENT
95
  Management::init();
96
  ThreadService::init();
97
  RuntimeService::init();
98
  ClassLoadingService::init();
99
  FinalizerService::init();
100
#else
101
  ThreadService::init();
102
#endif // INCLUDE_MANAGEMENT
103
}
104

105
#if INCLUDE_MANAGEMENT
106

107
void Management::init() {
108
  EXCEPTION_MARK;
109

110
  // These counters are for java.lang.management API support.
111
  // They are created even if -XX:-UsePerfData is set and in
112
  // that case, they will be allocated on C heap.
113

114
  _begin_vm_creation_time =
115
            PerfDataManager::create_variable(SUN_RT, "createVmBeginTime",
116
                                             PerfData::U_None, CHECK);
117

118
  _end_vm_creation_time =
119
            PerfDataManager::create_variable(SUN_RT, "createVmEndTime",
120
                                             PerfData::U_None, CHECK);
121

122
  _vm_init_done_time =
123
            PerfDataManager::create_variable(SUN_RT, "vmInitDoneTime",
124
                                             PerfData::U_None, CHECK);
125

126
  // Initialize optional support
127
  _optional_support.isLowMemoryDetectionSupported = 1;
128
  _optional_support.isCompilationTimeMonitoringSupported = 1;
129
  _optional_support.isThreadContentionMonitoringSupported = 1;
130

131
  if (os::is_thread_cpu_time_supported()) {
132
    _optional_support.isCurrentThreadCpuTimeSupported = 1;
133
    _optional_support.isOtherThreadCpuTimeSupported = 1;
134
  } else {
135
    _optional_support.isCurrentThreadCpuTimeSupported = 0;
136
    _optional_support.isOtherThreadCpuTimeSupported = 0;
137
  }
138

139
  _optional_support.isObjectMonitorUsageSupported = 1;
140
#if INCLUDE_SERVICES
141
  // This depends on the heap inspector
142
  _optional_support.isSynchronizerUsageSupported = 1;
143
#endif // INCLUDE_SERVICES
144
  _optional_support.isThreadAllocatedMemorySupported = 1;
145
  _optional_support.isRemoteDiagnosticCommandsSupported = 1;
146

147
  // Registration of the diagnostic commands
148
  DCmd::register_dcmds();
149
}
150

151
void Management::initialize(TRAPS) {
152
  if (UseNotificationThread) {
153
    NotificationThread::initialize();
154
  }
155
  if (ManagementServer) {
156
    ResourceMark rm(THREAD);
157
    HandleMark hm(THREAD);
158

159
    // Load and initialize the jdk.internal.agent.Agent class
160
    // invoke startAgent method to start the management server
161
    Handle loader = Handle(THREAD, SystemDictionary::java_system_loader());
162
    Klass* k = SystemDictionary::resolve_or_null(vmSymbols::jdk_internal_agent_Agent(),
163
                                                   loader,
164
                                                   Handle(),
165
                                                   THREAD);
166
    if (k == nullptr) {
167
      vm_exit_during_initialization("Management agent initialization failure: "
168
          "class jdk.internal.agent.Agent not found.");
169
    }
170

171
    JavaValue result(T_VOID);
172
    JavaCalls::call_static(&result,
173
                           k,
174
                           vmSymbols::startAgent_name(),
175
                           vmSymbols::void_method_signature(),
176
                           CHECK);
177
  }
178
}
179

180
void Management::get_optional_support(jmmOptionalSupport* support) {
181
  memcpy(support, &_optional_support, sizeof(jmmOptionalSupport));
182
}
183

184
InstanceKlass* Management::load_and_initialize_klass(Symbol* sh, TRAPS) {
185
  Klass* k = SystemDictionary::resolve_or_fail(sh, true, CHECK_NULL);
186
  return initialize_klass(k, THREAD);
187
}
188

189
InstanceKlass* Management::load_and_initialize_klass_or_null(Symbol* sh, TRAPS) {
190
  Klass* k = SystemDictionary::resolve_or_null(sh, CHECK_NULL);
191
  if (k == nullptr) {
192
     return nullptr;
193
  }
194
  return initialize_klass(k, THREAD);
195
}
196

197
InstanceKlass* Management::initialize_klass(Klass* k, TRAPS) {
198
  InstanceKlass* ik = InstanceKlass::cast(k);
199
  if (ik->should_be_initialized()) {
200
    ik->initialize(CHECK_NULL);
201
  }
202
  // If these classes change to not be owned by the boot loader, they need
203
  // to be walked to keep their class loader alive in oops_do.
204
  assert(ik->class_loader() == nullptr, "need to follow in oops_do");
205
  return ik;
206
}
207

208

209
void Management::record_vm_init_completed() {
210
  // Initialize the timestamp to get the current time
211
  _vm_init_done_time->set_value(os::javaTimeMillis());
212

213
  // Update the timestamp to the vm init done time
214
  _stamp.update();
215
}
216

217
void Management::record_vm_startup_time(jlong begin, jlong duration) {
218
  // if the performance counter is not initialized,
219
  // then vm initialization failed; simply return.
220
  if (_begin_vm_creation_time == nullptr) return;
221

222
  _begin_vm_creation_time->set_value(begin);
223
  _end_vm_creation_time->set_value(begin + duration);
224
  PerfMemory::set_accessible(true);
225
}
226

227
jlong Management::begin_vm_creation_time() {
228
  return _begin_vm_creation_time->get_value();
229
}
230

231
jlong Management::vm_init_done_time() {
232
  return _vm_init_done_time->get_value();
233
}
234

235
jlong Management::timestamp() {
236
  TimeStamp t;
237
  t.update();
238
  return t.ticks() - _stamp.ticks();
239
}
240

241
InstanceKlass* Management::java_lang_management_ThreadInfo_klass(TRAPS) {
242
  if (_threadInfo_klass == nullptr) {
243
    _threadInfo_klass = load_and_initialize_klass(vmSymbols::java_lang_management_ThreadInfo(), CHECK_NULL);
244
  }
245
  return _threadInfo_klass;
246
}
247

248
InstanceKlass* Management::java_lang_management_MemoryUsage_klass(TRAPS) {
249
  if (_memoryUsage_klass == nullptr) {
250
    _memoryUsage_klass = load_and_initialize_klass(vmSymbols::java_lang_management_MemoryUsage(), CHECK_NULL);
251
  }
252
  return _memoryUsage_klass;
253
}
254

255
InstanceKlass* Management::java_lang_management_MemoryPoolMXBean_klass(TRAPS) {
256
  if (_memoryPoolMXBean_klass == nullptr) {
257
    _memoryPoolMXBean_klass = load_and_initialize_klass(vmSymbols::java_lang_management_MemoryPoolMXBean(), CHECK_NULL);
258
  }
259
  return _memoryPoolMXBean_klass;
260
}
261

262
InstanceKlass* Management::java_lang_management_MemoryManagerMXBean_klass(TRAPS) {
263
  if (_memoryManagerMXBean_klass == nullptr) {
264
    _memoryManagerMXBean_klass = load_and_initialize_klass(vmSymbols::java_lang_management_MemoryManagerMXBean(), CHECK_NULL);
265
  }
266
  return _memoryManagerMXBean_klass;
267
}
268

269
InstanceKlass* Management::java_lang_management_GarbageCollectorMXBean_klass(TRAPS) {
270
  if (_garbageCollectorMXBean_klass == nullptr) {
271
      _garbageCollectorMXBean_klass = load_and_initialize_klass(vmSymbols::java_lang_management_GarbageCollectorMXBean(), CHECK_NULL);
272
  }
273
  return _garbageCollectorMXBean_klass;
274
}
275

276
InstanceKlass* Management::sun_management_Sensor_klass(TRAPS) {
277
  if (_sensor_klass == nullptr) {
278
    _sensor_klass = load_and_initialize_klass(vmSymbols::sun_management_Sensor(), CHECK_NULL);
279
  }
280
  return _sensor_klass;
281
}
282

283
InstanceKlass* Management::sun_management_ManagementFactoryHelper_klass(TRAPS) {
284
  if (_managementFactoryHelper_klass == nullptr) {
285
    _managementFactoryHelper_klass = load_and_initialize_klass(vmSymbols::sun_management_ManagementFactoryHelper(), CHECK_NULL);
286
  }
287
  return _managementFactoryHelper_klass;
288
}
289

290
InstanceKlass* Management::com_sun_management_internal_GarbageCollectorExtImpl_klass(TRAPS) {
291
  if (_garbageCollectorExtImpl_klass == nullptr) {
292
    _garbageCollectorExtImpl_klass =
293
                load_and_initialize_klass_or_null(vmSymbols::com_sun_management_internal_GarbageCollectorExtImpl(), CHECK_NULL);
294
  }
295
  return _garbageCollectorExtImpl_klass;
296
}
297

298
InstanceKlass* Management::com_sun_management_GcInfo_klass(TRAPS) {
299
  if (_gcInfo_klass == nullptr) {
300
    _gcInfo_klass = load_and_initialize_klass(vmSymbols::com_sun_management_GcInfo(), CHECK_NULL);
301
  }
302
  return _gcInfo_klass;
303
}
304

305
InstanceKlass* Management::com_sun_management_internal_DiagnosticCommandImpl_klass(TRAPS) {
306
  if (_diagnosticCommandImpl_klass == nullptr) {
307
    _diagnosticCommandImpl_klass = load_and_initialize_klass(vmSymbols::com_sun_management_internal_DiagnosticCommandImpl(), CHECK_NULL);
308
  }
309
  return _diagnosticCommandImpl_klass;
310
}
311

312
static void initialize_ThreadInfo_constructor_arguments(JavaCallArguments* args, ThreadSnapshot* snapshot, TRAPS) {
313
  Handle snapshot_thread(THREAD, snapshot->threadObj());
314

315
  jlong contended_time;
316
  jlong waited_time;
317
  if (ThreadService::is_thread_monitoring_contention()) {
318
    contended_time = Management::ticks_to_ms(snapshot->contended_enter_ticks());
319
    waited_time = Management::ticks_to_ms(snapshot->monitor_wait_ticks() + snapshot->sleep_ticks());
320
  } else {
321
    // set them to -1 if thread contention monitoring is disabled.
322
    contended_time = max_julong;
323
    waited_time = max_julong;
324
  }
325

326
  int thread_status = static_cast<int>(snapshot->thread_status());
327
  assert((thread_status & JMM_THREAD_STATE_FLAG_MASK) == 0, "Flags already set in thread_status in Thread object");
328
  if (snapshot->is_suspended()) {
329
    thread_status |= JMM_THREAD_STATE_FLAG_SUSPENDED;
330
  }
331
  if (snapshot->is_in_native()) {
332
    thread_status |= JMM_THREAD_STATE_FLAG_NATIVE;
333
  }
334

335
  ThreadStackTrace* st = snapshot->get_stack_trace();
336
  Handle stacktrace_h;
337
  if (st != nullptr) {
338
    stacktrace_h = st->allocate_fill_stack_trace_element_array(CHECK);
339
  } else {
340
    stacktrace_h = Handle();
341
  }
342

343
  args->push_oop(snapshot_thread);
344
  args->push_int(thread_status);
345
  args->push_oop(Handle(THREAD, snapshot->blocker_object()));
346
  args->push_oop(Handle(THREAD, snapshot->blocker_object_owner()));
347
  args->push_long(snapshot->contended_enter_count());
348
  args->push_long(contended_time);
349
  args->push_long(snapshot->monitor_wait_count() + snapshot->sleep_count());
350
  args->push_long(waited_time);
351
  args->push_oop(stacktrace_h);
352
}
353

354
// Helper function to construct a ThreadInfo object
355
instanceOop Management::create_thread_info_instance(ThreadSnapshot* snapshot, TRAPS) {
356
  InstanceKlass* ik = Management::java_lang_management_ThreadInfo_klass(CHECK_NULL);
357
  JavaCallArguments args(14);
358

359
  // initialize the arguments for the ThreadInfo constructor
360
  initialize_ThreadInfo_constructor_arguments(&args, snapshot, CHECK_NULL);
361

362
  // Call ThreadInfo constructor with no locked monitors and synchronizers
363
  Handle element = JavaCalls::construct_new_instance(
364
                          ik,
365
                          vmSymbols::java_lang_management_ThreadInfo_constructor_signature(),
366
                          &args,
367
                          CHECK_NULL);
368
  return (instanceOop) element();
369
}
370

371
instanceOop Management::create_thread_info_instance(ThreadSnapshot* snapshot,
372
                                                    objArrayHandle monitors_array,
373
                                                    typeArrayHandle depths_array,
374
                                                    objArrayHandle synchronizers_array,
375
                                                    TRAPS) {
376
  InstanceKlass* ik = Management::java_lang_management_ThreadInfo_klass(CHECK_NULL);
377
  JavaCallArguments args(17);
378

379
  // initialize the arguments for the ThreadInfo constructor
380
  initialize_ThreadInfo_constructor_arguments(&args, snapshot, CHECK_NULL);
381

382
  // push the locked monitors and synchronizers in the arguments
383
  args.push_oop(monitors_array);
384
  args.push_oop(depths_array);
385
  args.push_oop(synchronizers_array);
386

387
  // Call ThreadInfo constructor with locked monitors and synchronizers
388
  Handle element = JavaCalls::construct_new_instance(
389
                          ik,
390
                          vmSymbols::java_lang_management_ThreadInfo_with_locks_constructor_signature(),
391
                          &args,
392
                          CHECK_NULL);
393
  return (instanceOop) element();
394
}
395

396

397
static GCMemoryManager* get_gc_memory_manager_from_jobject(jobject mgr, TRAPS) {
398
  if (mgr == nullptr) {
399
    THROW_(vmSymbols::java_lang_NullPointerException(), nullptr);
400
  }
401
  oop mgr_obj = JNIHandles::resolve(mgr);
402
  instanceHandle h(THREAD, (instanceOop) mgr_obj);
403

404
  InstanceKlass* k = Management::java_lang_management_GarbageCollectorMXBean_klass(CHECK_NULL);
405
  if (!h->is_a(k)) {
406
    THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(),
407
               "the object is not an instance of java.lang.management.GarbageCollectorMXBean class",
408
               nullptr);
409
  }
410

411
  MemoryManager* gc = MemoryService::get_memory_manager(h);
412
  if (gc == nullptr || !gc->is_gc_memory_manager()) {
413
    THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(),
414
               "Invalid GC memory manager",
415
               nullptr);
416
  }
417
  return (GCMemoryManager*) gc;
418
}
419

420
static MemoryPool* get_memory_pool_from_jobject(jobject obj, TRAPS) {
421
  if (obj == nullptr) {
422
    THROW_(vmSymbols::java_lang_NullPointerException(), nullptr);
423
  }
424

425
  oop pool_obj = JNIHandles::resolve(obj);
426
  assert(pool_obj->is_instance(), "Should be an instanceOop");
427
  instanceHandle ph(THREAD, (instanceOop) pool_obj);
428

429
  return MemoryService::get_memory_pool(ph);
430
}
431

432
static void validate_thread_id_array(typeArrayHandle ids_ah, TRAPS) {
433
  int num_threads = ids_ah->length();
434

435
  // Validate input thread IDs
436
  int i = 0;
437
  for (i = 0; i < num_threads; i++) {
438
    jlong tid = ids_ah->long_at(i);
439
    if (tid <= 0) {
440
      // throw exception if invalid thread id.
441
      THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
442
                "Invalid thread ID entry");
443
    }
444
  }
445
}
446

447
// Returns true if the JavaThread's Java object is a platform thread
448
static bool is_platform_thread(JavaThread* jt) {
449
  if (jt != nullptr) {
450
    oop thread_obj = jt->threadObj();
451
    return (thread_obj != nullptr) && !thread_obj->is_a(vmClasses::BoundVirtualThread_klass());
452
  } else {
453
    return false;
454
  }
455
}
456

457
static void validate_thread_info_array(objArrayHandle infoArray_h, TRAPS) {
458
  // check if the element of infoArray is of type ThreadInfo class
459
  Klass* threadinfo_klass = Management::java_lang_management_ThreadInfo_klass(CHECK);
460
  Klass* element_klass = ObjArrayKlass::cast(infoArray_h->klass())->element_klass();
461
  if (element_klass != threadinfo_klass) {
462
    THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
463
              "infoArray element type is not ThreadInfo class");
464
  }
465
}
466

467
// Returns true if the ThreadSnapshot's Java object is a platform thread
468
static bool is_platform_thread(ThreadSnapshot* ts) {
469
  oop thread_obj = ts->threadObj();
470
  return (thread_obj != nullptr) && !thread_obj->is_a(vmClasses::BoundVirtualThread_klass());
471
}
472

473
static MemoryManager* get_memory_manager_from_jobject(jobject obj, TRAPS) {
474
  if (obj == nullptr) {
475
    THROW_(vmSymbols::java_lang_NullPointerException(), nullptr);
476
  }
477

478
  oop mgr_obj = JNIHandles::resolve(obj);
479
  assert(mgr_obj->is_instance(), "Should be an instanceOop");
480
  instanceHandle mh(THREAD, (instanceOop) mgr_obj);
481

482
  return MemoryService::get_memory_manager(mh);
483
}
484

485
// Returns a version string and sets major and minor version if
486
// the input parameters are non-null.
487
JVM_LEAF(jint, jmm_GetVersion(JNIEnv *env))
488
  return JMM_VERSION;
489
JVM_END
490

491
// Gets the list of VM monitoring and management optional supports
492
// Returns 0 if succeeded; otherwise returns non-zero.
493
JVM_LEAF(jint, jmm_GetOptionalSupport(JNIEnv *env, jmmOptionalSupport* support))
494
  if (support == nullptr) {
495
    return -1;
496
  }
497
  Management::get_optional_support(support);
498
  return 0;
499
JVM_END
500

501
// Returns an array of java/lang/management/MemoryPoolMXBean object
502
// one for each memory pool if obj == null; otherwise returns
503
// an array of memory pools for a given memory manager if
504
// it is a valid memory manager.
505
JVM_ENTRY(jobjectArray, jmm_GetMemoryPools(JNIEnv* env, jobject obj))
506
  ResourceMark rm(THREAD);
507

508
  int num_memory_pools;
509
  MemoryManager* mgr = nullptr;
510
  if (obj == nullptr) {
511
    num_memory_pools = MemoryService::num_memory_pools();
512
  } else {
513
    mgr = get_memory_manager_from_jobject(obj, CHECK_NULL);
514
    if (mgr == nullptr) {
515
      return nullptr;
516
    }
517
    num_memory_pools = mgr->num_memory_pools();
518
  }
519

520
  // Allocate the resulting MemoryPoolMXBean[] object
521
  InstanceKlass* ik = Management::java_lang_management_MemoryPoolMXBean_klass(CHECK_NULL);
522
  objArrayOop r = oopFactory::new_objArray(ik, num_memory_pools, CHECK_NULL);
523
  objArrayHandle poolArray(THREAD, r);
524

525
  if (mgr == nullptr) {
526
    // Get all memory pools
527
    for (int i = 0; i < num_memory_pools; i++) {
528
      MemoryPool* pool = MemoryService::get_memory_pool(i);
529
      instanceOop p = pool->get_memory_pool_instance(CHECK_NULL);
530
      instanceHandle ph(THREAD, p);
531
      poolArray->obj_at_put(i, ph());
532
    }
533
  } else {
534
    // Get memory pools managed by a given memory manager
535
    for (int i = 0; i < num_memory_pools; i++) {
536
      MemoryPool* pool = mgr->get_memory_pool(i);
537
      instanceOop p = pool->get_memory_pool_instance(CHECK_NULL);
538
      instanceHandle ph(THREAD, p);
539
      poolArray->obj_at_put(i, ph());
540
    }
541
  }
542
  return (jobjectArray) JNIHandles::make_local(THREAD, poolArray());
543
JVM_END
544

545
// Returns an array of java/lang/management/MemoryManagerMXBean object
546
// one for each memory manager if obj == null; otherwise returns
547
// an array of memory managers for a given memory pool if
548
// it is a valid memory pool.
549
JVM_ENTRY(jobjectArray, jmm_GetMemoryManagers(JNIEnv* env, jobject obj))
550
  ResourceMark rm(THREAD);
551

552
  int num_mgrs;
553
  MemoryPool* pool = nullptr;
554
  if (obj == nullptr) {
555
    num_mgrs = MemoryService::num_memory_managers();
556
  } else {
557
    pool = get_memory_pool_from_jobject(obj, CHECK_NULL);
558
    if (pool == nullptr) {
559
      return nullptr;
560
    }
561
    num_mgrs = pool->num_memory_managers();
562
  }
563

564
  // Allocate the resulting MemoryManagerMXBean[] object
565
  InstanceKlass* ik = Management::java_lang_management_MemoryManagerMXBean_klass(CHECK_NULL);
566
  objArrayOop r = oopFactory::new_objArray(ik, num_mgrs, CHECK_NULL);
567
  objArrayHandle mgrArray(THREAD, r);
568

569
  if (pool == nullptr) {
570
    // Get all memory managers
571
    for (int i = 0; i < num_mgrs; i++) {
572
      MemoryManager* mgr = MemoryService::get_memory_manager(i);
573
      instanceOop p = mgr->get_memory_manager_instance(CHECK_NULL);
574
      instanceHandle ph(THREAD, p);
575
      mgrArray->obj_at_put(i, ph());
576
    }
577
  } else {
578
    // Get memory managers for a given memory pool
579
    for (int i = 0; i < num_mgrs; i++) {
580
      MemoryManager* mgr = pool->get_memory_manager(i);
581
      instanceOop p = mgr->get_memory_manager_instance(CHECK_NULL);
582
      instanceHandle ph(THREAD, p);
583
      mgrArray->obj_at_put(i, ph());
584
    }
585
  }
586
  return (jobjectArray) JNIHandles::make_local(THREAD, mgrArray());
587
JVM_END
588

589

590
// Returns a java/lang/management/MemoryUsage object containing the memory usage
591
// of a given memory pool.
592
JVM_ENTRY(jobject, jmm_GetMemoryPoolUsage(JNIEnv* env, jobject obj))
593
  ResourceMark rm(THREAD);
594

595
  MemoryPool* pool = get_memory_pool_from_jobject(obj, CHECK_NULL);
596
  if (pool != nullptr) {
597
    MemoryUsage usage = pool->get_memory_usage();
598
    Handle h = MemoryService::create_MemoryUsage_obj(usage, CHECK_NULL);
599
    return JNIHandles::make_local(THREAD, h());
600
  } else {
601
    return nullptr;
602
  }
603
JVM_END
604

605
// Returns a java/lang/management/MemoryUsage object containing the memory usage
606
// of a given memory pool.
607
JVM_ENTRY(jobject, jmm_GetPeakMemoryPoolUsage(JNIEnv* env, jobject obj))
608
  ResourceMark rm(THREAD);
609

610
  MemoryPool* pool = get_memory_pool_from_jobject(obj, CHECK_NULL);
611
  if (pool != nullptr) {
612
    MemoryUsage usage = pool->get_peak_memory_usage();
613
    Handle h = MemoryService::create_MemoryUsage_obj(usage, CHECK_NULL);
614
    return JNIHandles::make_local(THREAD, h());
615
  } else {
616
    return nullptr;
617
  }
618
JVM_END
619

620
// Returns a java/lang/management/MemoryUsage object containing the memory usage
621
// of a given memory pool after most recent GC.
622
JVM_ENTRY(jobject, jmm_GetPoolCollectionUsage(JNIEnv* env, jobject obj))
623
  ResourceMark rm(THREAD);
624

625
  MemoryPool* pool = get_memory_pool_from_jobject(obj, CHECK_NULL);
626
  if (pool != nullptr && pool->is_collected_pool()) {
627
    MemoryUsage usage = pool->get_last_collection_usage();
628
    Handle h = MemoryService::create_MemoryUsage_obj(usage, CHECK_NULL);
629
    return JNIHandles::make_local(THREAD, h());
630
  } else {
631
    return nullptr;
632
  }
633
JVM_END
634

635
// Sets the memory pool sensor for a threshold type
636
JVM_ENTRY(void, jmm_SetPoolSensor(JNIEnv* env, jobject obj, jmmThresholdType type, jobject sensorObj))
637
  if (obj == nullptr || sensorObj == nullptr) {
638
    THROW(vmSymbols::java_lang_NullPointerException());
639
  }
640

641
  InstanceKlass* sensor_klass = Management::sun_management_Sensor_klass(CHECK);
642
  oop s = JNIHandles::resolve(sensorObj);
643
  assert(s->is_instance(), "Sensor should be an instanceOop");
644
  instanceHandle sensor_h(THREAD, (instanceOop) s);
645
  if (!sensor_h->is_a(sensor_klass)) {
646
    THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
647
              "Sensor is not an instance of sun.management.Sensor class");
648
  }
649

650
  MemoryPool* mpool = get_memory_pool_from_jobject(obj, CHECK);
651
  assert(mpool != nullptr, "MemoryPool should exist");
652

653
  switch (type) {
654
    case JMM_USAGE_THRESHOLD_HIGH:
655
    case JMM_USAGE_THRESHOLD_LOW:
656
      // have only one sensor for threshold high and low
657
      mpool->set_usage_sensor_obj(sensor_h);
658
      break;
659
    case JMM_COLLECTION_USAGE_THRESHOLD_HIGH:
660
    case JMM_COLLECTION_USAGE_THRESHOLD_LOW:
661
      // have only one sensor for threshold high and low
662
      mpool->set_gc_usage_sensor_obj(sensor_h);
663
      break;
664
    default:
665
      assert(false, "Unrecognized type");
666
  }
667

668
JVM_END
669

670

671
// Sets the threshold of a given memory pool.
672
// Returns the previous threshold.
673
//
674
// Input parameters:
675
//   pool      - the MemoryPoolMXBean object
676
//   type      - threshold type
677
//   threshold - the new threshold (must not be negative)
678
//
679
JVM_ENTRY(jlong, jmm_SetPoolThreshold(JNIEnv* env, jobject obj, jmmThresholdType type, jlong threshold))
680
  if (threshold < 0) {
681
    THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(),
682
               "Invalid threshold value",
683
               -1);
684
  }
685

686
  if ((size_t)threshold > max_uintx) {
687
    stringStream st;
688
    st.print("Invalid valid threshold value. Threshold value (" JLONG_FORMAT ") > max value of size_t (" UINTX_FORMAT ")", threshold, max_uintx);
689
    THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(), st.as_string(), -1);
690
  }
691

692
  MemoryPool* pool = get_memory_pool_from_jobject(obj, CHECK_(0L));
693
  assert(pool != nullptr, "MemoryPool should exist");
694

695
  jlong prev = 0;
696
  switch (type) {
697
    case JMM_USAGE_THRESHOLD_HIGH:
698
      if (!pool->usage_threshold()->is_high_threshold_supported()) {
699
        return -1;
700
      }
701
      prev = pool->usage_threshold()->set_high_threshold((size_t) threshold);
702
      break;
703

704
    case JMM_USAGE_THRESHOLD_LOW:
705
      if (!pool->usage_threshold()->is_low_threshold_supported()) {
706
        return -1;
707
      }
708
      prev = pool->usage_threshold()->set_low_threshold((size_t) threshold);
709
      break;
710

711
    case JMM_COLLECTION_USAGE_THRESHOLD_HIGH:
712
      if (!pool->gc_usage_threshold()->is_high_threshold_supported()) {
713
        return -1;
714
      }
715
      // return and the new threshold is effective for the next GC
716
      return pool->gc_usage_threshold()->set_high_threshold((size_t) threshold);
717

718
    case JMM_COLLECTION_USAGE_THRESHOLD_LOW:
719
      if (!pool->gc_usage_threshold()->is_low_threshold_supported()) {
720
        return -1;
721
      }
722
      // return and the new threshold is effective for the next GC
723
      return pool->gc_usage_threshold()->set_low_threshold((size_t) threshold);
724

725
    default:
726
      assert(false, "Unrecognized type");
727
      return -1;
728
  }
729

730
  // When the threshold is changed, reevaluate if the low memory
731
  // detection is enabled.
732
  if (prev != threshold) {
733
    LowMemoryDetector::recompute_enabled_for_collected_pools();
734
    LowMemoryDetector::detect_low_memory(pool);
735
  }
736
  return prev;
737
JVM_END
738

739
// Returns a java/lang/management/MemoryUsage object representing
740
// the memory usage for the heap or non-heap memory.
741
JVM_ENTRY(jobject, jmm_GetMemoryUsage(JNIEnv* env, jboolean heap))
742
  ResourceMark rm(THREAD);
743

744
  MemoryUsage usage;
745

746
  if (heap) {
747
    usage = Universe::heap()->memory_usage();
748
  } else {
749
    // Calculate the memory usage by summing up the pools.
750
    size_t total_init = 0;
751
    size_t total_used = 0;
752
    size_t total_committed = 0;
753
    size_t total_max = 0;
754
    bool   has_undefined_init_size = false;
755
    bool   has_undefined_max_size = false;
756

757
    for (int i = 0; i < MemoryService::num_memory_pools(); i++) {
758
      MemoryPool* pool = MemoryService::get_memory_pool(i);
759
      if (pool->is_non_heap()) {
760
        MemoryUsage u = pool->get_memory_usage();
761
        total_used += u.used();
762
        total_committed += u.committed();
763

764
        if (u.init_size() == MemoryUsage::undefined_size()) {
765
          has_undefined_init_size = true;
766
        }
767
        if (!has_undefined_init_size) {
768
          total_init += u.init_size();
769
        }
770

771
        if (u.max_size() == MemoryUsage::undefined_size()) {
772
          has_undefined_max_size = true;
773
        }
774
        if (!has_undefined_max_size) {
775
          total_max += u.max_size();
776
        }
777
      }
778
    }
779

780
    // if any one of the memory pool has undefined init_size or max_size,
781
    // set it to MemoryUsage::undefined_size()
782
    if (has_undefined_init_size) {
783
      total_init = MemoryUsage::undefined_size();
784
    }
785
    if (has_undefined_max_size) {
786
      total_max = MemoryUsage::undefined_size();
787
    }
788

789
    usage = MemoryUsage(total_init, total_used, total_committed, total_max);
790
  }
791

792
  Handle obj = MemoryService::create_MemoryUsage_obj(usage, CHECK_NULL);
793
  return JNIHandles::make_local(THREAD, obj());
794
JVM_END
795

796
// Returns the boolean value of a given attribute.
797
JVM_LEAF(jboolean, jmm_GetBoolAttribute(JNIEnv *env, jmmBoolAttribute att))
798
  switch (att) {
799
  case JMM_VERBOSE_GC:
800
    return MemoryService::get_verbose();
801
  case JMM_VERBOSE_CLASS:
802
    return ClassLoadingService::get_verbose();
803
  case JMM_THREAD_CONTENTION_MONITORING:
804
    return ThreadService::is_thread_monitoring_contention();
805
  case JMM_THREAD_CPU_TIME:
806
    return ThreadService::is_thread_cpu_time_enabled();
807
  case JMM_THREAD_ALLOCATED_MEMORY:
808
    return ThreadService::is_thread_allocated_memory_enabled();
809
  default:
810
    assert(0, "Unrecognized attribute");
811
    return false;
812
  }
813
JVM_END
814

815
// Sets the given boolean attribute and returns the previous value.
816
JVM_ENTRY(jboolean, jmm_SetBoolAttribute(JNIEnv *env, jmmBoolAttribute att, jboolean flag))
817
  switch (att) {
818
  case JMM_VERBOSE_GC:
819
    return MemoryService::set_verbose(flag != 0);
820
  case JMM_VERBOSE_CLASS:
821
    return ClassLoadingService::set_verbose(flag != 0);
822
  case JMM_THREAD_CONTENTION_MONITORING:
823
    return ThreadService::set_thread_monitoring_contention(flag != 0);
824
  case JMM_THREAD_CPU_TIME:
825
    return ThreadService::set_thread_cpu_time_enabled(flag != 0);
826
  case JMM_THREAD_ALLOCATED_MEMORY:
827
    return ThreadService::set_thread_allocated_memory_enabled(flag != 0);
828
  default:
829
    assert(0, "Unrecognized attribute");
830
    return false;
831
  }
832
JVM_END
833

834

835
static jlong get_gc_attribute(GCMemoryManager* mgr, jmmLongAttribute att) {
836
  switch (att) {
837
  case JMM_GC_TIME_MS:
838
    return mgr->gc_time_ms();
839

840
  case JMM_GC_COUNT:
841
    return mgr->gc_count();
842

843
  case JMM_GC_EXT_ATTRIBUTE_INFO_SIZE:
844
    // current implementation only has 1 ext attribute
845
    return 1;
846

847
  default:
848
    assert(0, "Unrecognized GC attribute");
849
    return -1;
850
  }
851
}
852

853
class VmThreadCountClosure: public ThreadClosure {
854
 private:
855
  int _count;
856
 public:
857
  VmThreadCountClosure() : _count(0) {};
858
  void do_thread(Thread* thread);
859
  int count() { return _count; }
860
};
861

862
void VmThreadCountClosure::do_thread(Thread* thread) {
863
  // exclude externally visible JavaThreads
864
  if (thread->is_Java_thread() && !thread->is_hidden_from_external_view()) {
865
    return;
866
  }
867

868
  _count++;
869
}
870

871
static jint get_vm_thread_count() {
872
  VmThreadCountClosure vmtcc;
873
  {
874
    MutexLocker ml(Threads_lock);
875
    Threads::threads_do(&vmtcc);
876
  }
877

878
  return vmtcc.count();
879
}
880

881
static jint get_num_flags() {
882
  // last flag entry is always null, so subtract 1
883
  int nFlags = (int) JVMFlag::numFlags - 1;
884
  int count = 0;
885
  for (int i = 0; i < nFlags; i++) {
886
    JVMFlag* flag = &JVMFlag::flags[i];
887
    // Exclude the locked (diagnostic, experimental) flags
888
    if (flag->is_unlocked() || flag->is_unlocker()) {
889
      count++;
890
    }
891
  }
892
  return count;
893
}
894

895
static jlong get_long_attribute(jmmLongAttribute att) {
896
  switch (att) {
897
  case JMM_CLASS_LOADED_COUNT:
898
    return ClassLoadingService::loaded_class_count();
899

900
  case JMM_CLASS_UNLOADED_COUNT:
901
    return ClassLoadingService::unloaded_class_count();
902

903
  case JMM_THREAD_TOTAL_COUNT:
904
    return ThreadService::get_total_thread_count();
905

906
  case JMM_THREAD_LIVE_COUNT:
907
    return ThreadService::get_live_thread_count();
908

909
  case JMM_THREAD_PEAK_COUNT:
910
    return ThreadService::get_peak_thread_count();
911

912
  case JMM_THREAD_DAEMON_COUNT:
913
    return ThreadService::get_daemon_thread_count();
914

915
  case JMM_JVM_INIT_DONE_TIME_MS:
916
    return Management::vm_init_done_time();
917

918
  case JMM_JVM_UPTIME_MS:
919
    return Management::ticks_to_ms(os::elapsed_counter());
920

921
  case JMM_COMPILE_TOTAL_TIME_MS:
922
    return Management::ticks_to_ms(CompileBroker::total_compilation_ticks());
923

924
  case JMM_OS_PROCESS_ID:
925
    return os::current_process_id();
926

927
  // Hotspot-specific counters
928
  case JMM_CLASS_LOADED_BYTES:
929
    return ClassLoadingService::loaded_class_bytes();
930

931
  case JMM_CLASS_UNLOADED_BYTES:
932
    return ClassLoadingService::unloaded_class_bytes();
933

934
  case JMM_SHARED_CLASS_LOADED_COUNT:
935
    return ClassLoadingService::loaded_shared_class_count();
936

937
  case JMM_SHARED_CLASS_UNLOADED_COUNT:
938
    return ClassLoadingService::unloaded_shared_class_count();
939

940

941
  case JMM_SHARED_CLASS_LOADED_BYTES:
942
    return ClassLoadingService::loaded_shared_class_bytes();
943

944
  case JMM_SHARED_CLASS_UNLOADED_BYTES:
945
    return ClassLoadingService::unloaded_shared_class_bytes();
946

947
  case JMM_TOTAL_CLASSLOAD_TIME_MS:
948
    return ClassLoader::classloader_time_ms();
949

950
  case JMM_VM_GLOBAL_COUNT:
951
    return get_num_flags();
952

953
  case JMM_SAFEPOINT_COUNT:
954
    return RuntimeService::safepoint_count();
955

956
  case JMM_TOTAL_SAFEPOINTSYNC_TIME_MS:
957
    return RuntimeService::safepoint_sync_time_ms();
958

959
  case JMM_TOTAL_STOPPED_TIME_MS:
960
    return RuntimeService::safepoint_time_ms();
961

962
  case JMM_TOTAL_APP_TIME_MS:
963
    return RuntimeService::application_time_ms();
964

965
  case JMM_VM_THREAD_COUNT:
966
    return get_vm_thread_count();
967

968
  case JMM_CLASS_INIT_TOTAL_COUNT:
969
    return ClassLoader::class_init_count();
970

971
  case JMM_CLASS_INIT_TOTAL_TIME_MS:
972
    return ClassLoader::class_init_time_ms();
973

974
  case JMM_CLASS_VERIFY_TOTAL_TIME_MS:
975
    return ClassLoader::class_verify_time_ms();
976

977
  case JMM_METHOD_DATA_SIZE_BYTES:
978
    return ClassLoadingService::class_method_data_size();
979

980
  case JMM_OS_MEM_TOTAL_PHYSICAL_BYTES:
981
    return os::physical_memory();
982

983
  default:
984
    return -1;
985
  }
986
}
987

988

989
// Returns the long value of a given attribute.
990
JVM_ENTRY(jlong, jmm_GetLongAttribute(JNIEnv *env, jobject obj, jmmLongAttribute att))
991
  if (obj == nullptr) {
992
    return get_long_attribute(att);
993
  } else {
994
    GCMemoryManager* mgr = get_gc_memory_manager_from_jobject(obj, CHECK_(0L));
995
    if (mgr != nullptr) {
996
      return get_gc_attribute(mgr, att);
997
    }
998
  }
999
  return -1;
1000
JVM_END
1001

1002
// Gets the value of all attributes specified in the given array
1003
// and sets the value in the result array.
1004
// Returns the number of attributes found.
1005
JVM_ENTRY(jint, jmm_GetLongAttributes(JNIEnv *env,
1006
                                      jobject obj,
1007
                                      jmmLongAttribute* atts,
1008
                                      jint count,
1009
                                      jlong* result))
1010

1011
  int num_atts = 0;
1012
  if (obj == nullptr) {
1013
    for (int i = 0; i < count; i++) {
1014
      result[i] = get_long_attribute(atts[i]);
1015
      if (result[i] != -1) {
1016
        num_atts++;
1017
      }
1018
    }
1019
  } else {
1020
    GCMemoryManager* mgr = get_gc_memory_manager_from_jobject(obj, CHECK_0);
1021
    for (int i = 0; i < count; i++) {
1022
      result[i] = get_gc_attribute(mgr, atts[i]);
1023
      if (result[i] != -1) {
1024
        num_atts++;
1025
      }
1026
    }
1027
  }
1028
  return num_atts;
1029
JVM_END
1030

1031
// Helper function to do thread dump for a specific list of threads
1032
static void do_thread_dump(ThreadDumpResult* dump_result,
1033
                           typeArrayHandle ids_ah,  // array of thread ID (long[])
1034
                           int num_threads,
1035
                           int max_depth,
1036
                           bool with_locked_monitors,
1037
                           bool with_locked_synchronizers,
1038
                           TRAPS) {
1039
  // no need to actually perform thread dump if no TIDs are specified
1040
  if (num_threads == 0) return;
1041

1042
  // First get an array of threadObj handles.
1043
  // A JavaThread may terminate before we get the stack trace.
1044
  GrowableArray<instanceHandle>* thread_handle_array = new GrowableArray<instanceHandle>(num_threads);
1045

1046
  {
1047
    // Need this ThreadsListHandle for converting Java thread IDs into
1048
    // threadObj handles; dump_result->set_t_list() is called in the
1049
    // VM op below so we can't use it yet.
1050
    ThreadsListHandle tlh;
1051
    for (int i = 0; i < num_threads; i++) {
1052
      jlong tid = ids_ah->long_at(i);
1053
      JavaThread* jt = tlh.list()->find_JavaThread_from_java_tid(tid);
1054
      oop thread_obj = is_platform_thread(jt) ? jt->threadObj() : (oop)nullptr;
1055
      instanceHandle threadObj_h(THREAD, (instanceOop) thread_obj);
1056
      thread_handle_array->append(threadObj_h);
1057
    }
1058
  }
1059

1060
  // Obtain thread dumps and thread snapshot information
1061
  VM_ThreadDump op(dump_result,
1062
                   thread_handle_array,
1063
                   num_threads,
1064
                   max_depth, /* stack depth */
1065
                   with_locked_monitors,
1066
                   with_locked_synchronizers);
1067
  VMThread::execute(&op);
1068
}
1069

1070
// Gets an array of ThreadInfo objects. Each element is the ThreadInfo
1071
// for the thread ID specified in the corresponding entry in
1072
// the given array of thread IDs; or null if the thread does not exist
1073
// or has terminated.
1074
//
1075
// Input parameters:
1076
//   ids       - array of thread IDs
1077
//   maxDepth  - the maximum depth of stack traces to be dumped:
1078
//               maxDepth == -1 requests to dump entire stack trace.
1079
//               maxDepth == 0  requests no stack trace.
1080
//   infoArray - array of ThreadInfo objects
1081
//
1082
// QQQ - Why does this method return a value instead of void?
1083
JVM_ENTRY(jint, jmm_GetThreadInfo(JNIEnv *env, jlongArray ids, jint maxDepth, jobjectArray infoArray))
1084
  // Check if threads is null
1085
  if (ids == nullptr || infoArray == nullptr) {
1086
    THROW_(vmSymbols::java_lang_NullPointerException(), -1);
1087
  }
1088

1089
  if (maxDepth < -1) {
1090
    THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(),
1091
               "Invalid maxDepth", -1);
1092
  }
1093

1094
  ResourceMark rm(THREAD);
1095
  typeArrayOop ta = typeArrayOop(JNIHandles::resolve_non_null(ids));
1096
  typeArrayHandle ids_ah(THREAD, ta);
1097

1098
  oop infoArray_obj = JNIHandles::resolve_non_null(infoArray);
1099
  objArrayOop oa = objArrayOop(infoArray_obj);
1100
  objArrayHandle infoArray_h(THREAD, oa);
1101

1102
  // validate the thread id array
1103
  validate_thread_id_array(ids_ah, CHECK_0);
1104

1105
  // validate the ThreadInfo[] parameters
1106
  validate_thread_info_array(infoArray_h, CHECK_0);
1107

1108
  // infoArray must be of the same length as the given array of thread IDs
1109
  int num_threads = ids_ah->length();
1110
  if (num_threads != infoArray_h->length()) {
1111
    THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(),
1112
               "The length of the given ThreadInfo array does not match the length of the given array of thread IDs", -1);
1113
  }
1114

1115
  // Must use ThreadDumpResult to store the ThreadSnapshot.
1116
  // GC may occur after the thread snapshots are taken but before
1117
  // this function returns. The threadObj and other oops kept
1118
  // in the ThreadSnapshot are marked and adjusted during GC.
1119
  ThreadDumpResult dump_result(num_threads);
1120

1121
  if (maxDepth == 0) {
1122
    // No stack trace to dump so we do not need to stop the world.
1123
    // Since we never do the VM op here we must set the threads list.
1124
    dump_result.set_t_list();
1125
    for (int i = 0; i < num_threads; i++) {
1126
      jlong tid = ids_ah->long_at(i);
1127
      JavaThread* jt = dump_result.t_list()->find_JavaThread_from_java_tid(tid);
1128
      if (jt == nullptr) {
1129
        // if the thread does not exist or now it is terminated,
1130
        // create dummy snapshot
1131
        dump_result.add_thread_snapshot();
1132
      } else {
1133
        dump_result.add_thread_snapshot(jt);
1134
      }
1135
    }
1136
  } else {
1137
    // obtain thread dump with the specific list of threads with stack trace
1138
    do_thread_dump(&dump_result,
1139
                   ids_ah,
1140
                   num_threads,
1141
                   maxDepth,
1142
                   false, /* no locked monitor */
1143
                   false, /* no locked synchronizers */
1144
                   CHECK_0);
1145
  }
1146

1147
  int num_snapshots = dump_result.num_snapshots();
1148
  assert(num_snapshots == num_threads, "Must match the number of thread snapshots");
1149
  assert(num_snapshots == 0 || dump_result.t_list_has_been_set(), "ThreadsList must have been set if we have a snapshot");
1150
  int index = 0;
1151
  for (ThreadSnapshot* ts = dump_result.snapshots(); ts != nullptr; index++, ts = ts->next()) {
1152
    // For each thread, create an java/lang/management/ThreadInfo object
1153
    // and fill with the thread information
1154

1155
    if (!is_platform_thread(ts)) {
1156
      // if the thread does not exist, has terminated, or is a virtual thread, then set threadinfo to null
1157
      infoArray_h->obj_at_put(index, nullptr);
1158
      continue;
1159
    }
1160

1161
    // Create java.lang.management.ThreadInfo object
1162
    instanceOop info_obj = Management::create_thread_info_instance(ts, CHECK_0);
1163
    infoArray_h->obj_at_put(index, info_obj);
1164
  }
1165
  return 0;
1166
JVM_END
1167

1168
// Dump thread info for the specified threads.
1169
// It returns an array of ThreadInfo objects. Each element is the ThreadInfo
1170
// for the thread ID specified in the corresponding entry in
1171
// the given array of thread IDs; or null if the thread does not exist
1172
// or has terminated.
1173
//
1174
// Input parameter:
1175
//    ids - array of thread IDs; null indicates all live threads
1176
//    locked_monitors - if true, dump locked object monitors
1177
//    locked_synchronizers - if true, dump locked JSR-166 synchronizers
1178
//
1179
JVM_ENTRY(jobjectArray, jmm_DumpThreads(JNIEnv *env, jlongArray thread_ids, jboolean locked_monitors,
1180
                                        jboolean locked_synchronizers, jint maxDepth))
1181
  ResourceMark rm(THREAD);
1182

1183
  typeArrayOop ta = typeArrayOop(JNIHandles::resolve(thread_ids));
1184
  int num_threads = (ta != nullptr ? ta->length() : 0);
1185
  typeArrayHandle ids_ah(THREAD, ta);
1186

1187
  ThreadDumpResult dump_result(num_threads);  // can safepoint
1188

1189
  if (ids_ah() != nullptr) {
1190

1191
    // validate the thread id array
1192
    validate_thread_id_array(ids_ah, CHECK_NULL);
1193

1194
    // obtain thread dump of a specific list of threads
1195
    do_thread_dump(&dump_result,
1196
                   ids_ah,
1197
                   num_threads,
1198
                   maxDepth, /* stack depth */
1199
                   (locked_monitors ? true : false),      /* with locked monitors */
1200
                   (locked_synchronizers ? true : false), /* with locked synchronizers */
1201
                   CHECK_NULL);
1202
  } else {
1203
    // obtain thread dump of all threads
1204
    VM_ThreadDump op(&dump_result,
1205
                     maxDepth, /* stack depth */
1206
                     (locked_monitors ? true : false),     /* with locked monitors */
1207
                     (locked_synchronizers ? true : false) /* with locked synchronizers */);
1208
    VMThread::execute(&op);
1209
  }
1210

1211
  int num_snapshots = dump_result.num_snapshots();
1212
  assert(num_snapshots == 0 || dump_result.t_list_has_been_set(), "ThreadsList must have been set if we have a snapshot");
1213

1214
  // create the result ThreadInfo[] object
1215
  InstanceKlass* ik = Management::java_lang_management_ThreadInfo_klass(CHECK_NULL);
1216
  objArrayOop r = oopFactory::new_objArray(ik, num_snapshots, CHECK_NULL);
1217
  objArrayHandle result_h(THREAD, r);
1218

1219
  int index = 0;
1220
  for (ThreadSnapshot* ts = dump_result.snapshots(); ts != nullptr; ts = ts->next(), index++) {
1221
    if (!is_platform_thread(ts)) {
1222
      // if the thread does not exist, has terminated, or is a virtual thread, then set threadinfo to null
1223
      result_h->obj_at_put(index, nullptr);
1224
      continue;
1225
    }
1226

1227
    ThreadStackTrace* stacktrace = ts->get_stack_trace();
1228
    assert(stacktrace != nullptr, "Must have a stack trace dumped");
1229

1230
    // Create Object[] filled with locked monitors
1231
    // Create int[] filled with the stack depth where a monitor was locked
1232
    int num_frames = stacktrace->get_stack_depth();
1233
    int num_locked_monitors = stacktrace->num_jni_locked_monitors();
1234

1235
    // Count the total number of locked monitors
1236
    for (int i = 0; i < num_frames; i++) {
1237
      StackFrameInfo* frame = stacktrace->stack_frame_at(i);
1238
      num_locked_monitors += frame->num_locked_monitors();
1239
    }
1240

1241
    objArrayHandle monitors_array;
1242
    typeArrayHandle depths_array;
1243
    objArrayHandle synchronizers_array;
1244

1245
    if (locked_monitors) {
1246
      // Constructs Object[] and int[] to contain the object monitor and the stack depth
1247
      // where the thread locked it
1248
      objArrayOop array = oopFactory::new_objArray(vmClasses::Object_klass(), num_locked_monitors, CHECK_NULL);
1249
      objArrayHandle mh(THREAD, array);
1250
      monitors_array = mh;
1251

1252
      typeArrayOop tarray = oopFactory::new_typeArray(T_INT, num_locked_monitors, CHECK_NULL);
1253
      typeArrayHandle dh(THREAD, tarray);
1254
      depths_array = dh;
1255

1256
      int count = 0;
1257
      int j = 0;
1258
      for (int depth = 0; depth < num_frames; depth++) {
1259
        StackFrameInfo* frame = stacktrace->stack_frame_at(depth);
1260
        int len = frame->num_locked_monitors();
1261
        GrowableArray<OopHandle>* locked_monitors = frame->locked_monitors();
1262
        for (j = 0; j < len; j++) {
1263
          oop monitor = locked_monitors->at(j).resolve();
1264
          assert(monitor != nullptr, "must be a Java object");
1265
          monitors_array->obj_at_put(count, monitor);
1266
          depths_array->int_at_put(count, depth);
1267
          count++;
1268
        }
1269
      }
1270

1271
      GrowableArray<OopHandle>* jni_locked_monitors = stacktrace->jni_locked_monitors();
1272
      for (j = 0; j < jni_locked_monitors->length(); j++) {
1273
        oop object = jni_locked_monitors->at(j).resolve();
1274
        assert(object != nullptr, "must be a Java object");
1275
        monitors_array->obj_at_put(count, object);
1276
        // Monitor locked via JNI MonitorEnter call doesn't have stack depth info
1277
        depths_array->int_at_put(count, -1);
1278
        count++;
1279
      }
1280
      assert(count == num_locked_monitors, "number of locked monitors doesn't match");
1281
    }
1282

1283
    if (locked_synchronizers) {
1284
      // Create Object[] filled with locked JSR-166 synchronizers
1285
      assert(ts->threadObj() != nullptr, "Must be a valid JavaThread");
1286
      ThreadConcurrentLocks* tcl = ts->get_concurrent_locks();
1287
      GrowableArray<OopHandle>* locks = (tcl != nullptr ? tcl->owned_locks() : nullptr);
1288
      int num_locked_synchronizers = (locks != nullptr ? locks->length() : 0);
1289

1290
      objArrayOop array = oopFactory::new_objArray(vmClasses::Object_klass(), num_locked_synchronizers, CHECK_NULL);
1291
      objArrayHandle sh(THREAD, array);
1292
      synchronizers_array = sh;
1293

1294
      for (int k = 0; k < num_locked_synchronizers; k++) {
1295
        synchronizers_array->obj_at_put(k, locks->at(k).resolve());
1296
      }
1297
    }
1298

1299
    // Create java.lang.management.ThreadInfo object
1300
    instanceOop info_obj = Management::create_thread_info_instance(ts,
1301
                                                                   monitors_array,
1302
                                                                   depths_array,
1303
                                                                   synchronizers_array,
1304
                                                                   CHECK_NULL);
1305
    result_h->obj_at_put(index, info_obj);
1306
  }
1307

1308
  return (jobjectArray) JNIHandles::make_local(THREAD, result_h());
1309
JVM_END
1310

1311
// Reset statistic.  Return true if the requested statistic is reset.
1312
// Otherwise, return false.
1313
//
1314
// Input parameters:
1315
//  obj  - specify which instance the statistic associated with to be reset
1316
//         For PEAK_POOL_USAGE stat, obj is required to be a memory pool object.
1317
//         For THREAD_CONTENTION_COUNT and TIME stat, obj is required to be a thread ID.
1318
//  type - the type of statistic to be reset
1319
//
1320
JVM_ENTRY(jboolean, jmm_ResetStatistic(JNIEnv *env, jvalue obj, jmmStatisticType type))
1321
  ResourceMark rm(THREAD);
1322

1323
  switch (type) {
1324
    case JMM_STAT_PEAK_THREAD_COUNT:
1325
      ThreadService::reset_peak_thread_count();
1326
      return true;
1327

1328
    case JMM_STAT_THREAD_CONTENTION_COUNT:
1329
    case JMM_STAT_THREAD_CONTENTION_TIME: {
1330
      jlong tid = obj.j;
1331
      if (tid < 0) {
1332
        THROW_(vmSymbols::java_lang_IllegalArgumentException(), JNI_FALSE);
1333
      }
1334

1335
      // Look for the JavaThread of this given tid
1336
      JavaThreadIteratorWithHandle jtiwh;
1337
      if (tid == 0) {
1338
        // reset contention statistics for all threads if tid == 0
1339
        for (; JavaThread *java_thread = jtiwh.next(); ) {
1340
          if (type == JMM_STAT_THREAD_CONTENTION_COUNT) {
1341
            ThreadService::reset_contention_count_stat(java_thread);
1342
          } else {
1343
            ThreadService::reset_contention_time_stat(java_thread);
1344
          }
1345
        }
1346
      } else {
1347
        // reset contention statistics for a given thread
1348
        JavaThread* java_thread = jtiwh.list()->find_JavaThread_from_java_tid(tid);
1349
        if (java_thread == nullptr) {
1350
          return false;
1351
        }
1352

1353
        if (type == JMM_STAT_THREAD_CONTENTION_COUNT) {
1354
          ThreadService::reset_contention_count_stat(java_thread);
1355
        } else {
1356
          ThreadService::reset_contention_time_stat(java_thread);
1357
        }
1358
      }
1359
      return true;
1360
      break;
1361
    }
1362
    case JMM_STAT_PEAK_POOL_USAGE: {
1363
      jobject o = obj.l;
1364
      if (o == nullptr) {
1365
        THROW_(vmSymbols::java_lang_NullPointerException(), JNI_FALSE);
1366
      }
1367

1368
      oop pool_obj = JNIHandles::resolve(o);
1369
      assert(pool_obj->is_instance(), "Should be an instanceOop");
1370
      instanceHandle ph(THREAD, (instanceOop) pool_obj);
1371

1372
      MemoryPool* pool = MemoryService::get_memory_pool(ph);
1373
      if (pool != nullptr) {
1374
        pool->reset_peak_memory_usage();
1375
        return true;
1376
      }
1377
      break;
1378
    }
1379
    case JMM_STAT_GC_STAT: {
1380
      jobject o = obj.l;
1381
      if (o == nullptr) {
1382
        THROW_(vmSymbols::java_lang_NullPointerException(), JNI_FALSE);
1383
      }
1384

1385
      GCMemoryManager* mgr = get_gc_memory_manager_from_jobject(o, CHECK_false);
1386
      if (mgr != nullptr) {
1387
        mgr->reset_gc_stat();
1388
        return true;
1389
      }
1390
      break;
1391
    }
1392
    default:
1393
      assert(0, "Unknown Statistic Type");
1394
  }
1395
  return false;
1396
JVM_END
1397

1398
// Returns the fast estimate of CPU time consumed by
1399
// a given thread (in nanoseconds).
1400
// If thread_id == 0, return CPU time for the current thread.
1401
JVM_ENTRY(jlong, jmm_GetThreadCpuTime(JNIEnv *env, jlong thread_id))
1402
  if (!os::is_thread_cpu_time_supported()) {
1403
    return -1;
1404
  }
1405

1406
  if (thread_id < 0) {
1407
    THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(),
1408
               "Invalid thread ID", -1);
1409
  }
1410

1411
  JavaThread* java_thread = nullptr;
1412
  if (thread_id == 0) {
1413
    // current thread
1414
    return os::current_thread_cpu_time();
1415
  } else {
1416
    ThreadsListHandle tlh;
1417
    java_thread = tlh.list()->find_JavaThread_from_java_tid(thread_id);
1418
    if (is_platform_thread(java_thread)) {
1419
      return os::thread_cpu_time((Thread*) java_thread);
1420
    }
1421
  }
1422
  return -1;
1423
JVM_END
1424

1425
// Returns a String array of all VM global flag names
1426
JVM_ENTRY(jobjectArray, jmm_GetVMGlobalNames(JNIEnv *env))
1427
  // last flag entry is always null, so subtract 1
1428
  int nFlags = (int) JVMFlag::numFlags - 1;
1429
  // allocate a temp array
1430
  objArrayOop r = oopFactory::new_objArray(vmClasses::String_klass(),
1431
                                           nFlags, CHECK_NULL);
1432
  objArrayHandle flags_ah(THREAD, r);
1433
  int num_entries = 0;
1434
  for (int i = 0; i < nFlags; i++) {
1435
    JVMFlag* flag = &JVMFlag::flags[i];
1436
    // Exclude develop flags in product builds.
1437
    if (flag->is_constant_in_binary()) {
1438
      continue;
1439
    }
1440
    // Exclude the locked (experimental, diagnostic) flags
1441
    if (flag->is_unlocked() || flag->is_unlocker()) {
1442
      Handle s = java_lang_String::create_from_str(flag->name(), CHECK_NULL);
1443
      flags_ah->obj_at_put(num_entries, s());
1444
      num_entries++;
1445
    }
1446
  }
1447

1448
  if (num_entries < nFlags) {
1449
    // Return array of right length
1450
    objArrayOop res = oopFactory::new_objArray(vmClasses::String_klass(), num_entries, CHECK_NULL);
1451
    for(int i = 0; i < num_entries; i++) {
1452
      res->obj_at_put(i, flags_ah->obj_at(i));
1453
    }
1454
    return (jobjectArray)JNIHandles::make_local(THREAD, res);
1455
  }
1456

1457
  return (jobjectArray)JNIHandles::make_local(THREAD, flags_ah());
1458
JVM_END
1459

1460
// Utility function used by jmm_GetVMGlobals.  Returns false if flag type
1461
// can't be determined, true otherwise.  If false is returned, then *global
1462
// will be incomplete and invalid.
1463
static bool add_global_entry(Handle name, jmmVMGlobal *global, JVMFlag *flag, TRAPS) {
1464
  Handle flag_name;
1465
  if (name() == nullptr) {
1466
    flag_name = java_lang_String::create_from_str(flag->name(), CHECK_false);
1467
  } else {
1468
    flag_name = name;
1469
  }
1470
  global->name = (jstring)JNIHandles::make_local(THREAD, flag_name());
1471

1472
  if (flag->is_bool()) {
1473
    global->value.z = flag->get_bool() ? JNI_TRUE : JNI_FALSE;
1474
    global->type = JMM_VMGLOBAL_TYPE_JBOOLEAN;
1475
  } else if (flag->is_int()) {
1476
    global->value.j = (jlong)flag->get_int();
1477
    global->type = JMM_VMGLOBAL_TYPE_JLONG;
1478
  } else if (flag->is_uint()) {
1479
    global->value.j = (jlong)flag->get_uint();
1480
    global->type = JMM_VMGLOBAL_TYPE_JLONG;
1481
  } else if (flag->is_intx()) {
1482
    global->value.j = (jlong)flag->get_intx();
1483
    global->type = JMM_VMGLOBAL_TYPE_JLONG;
1484
  } else if (flag->is_uintx()) {
1485
    global->value.j = (jlong)flag->get_uintx();
1486
    global->type = JMM_VMGLOBAL_TYPE_JLONG;
1487
  } else if (flag->is_uint64_t()) {
1488
    global->value.j = (jlong)flag->get_uint64_t();
1489
    global->type = JMM_VMGLOBAL_TYPE_JLONG;
1490
  } else if (flag->is_double()) {
1491
    global->value.d = (jdouble)flag->get_double();
1492
    global->type = JMM_VMGLOBAL_TYPE_JDOUBLE;
1493
  } else if (flag->is_size_t()) {
1494
    global->value.j = (jlong)flag->get_size_t();
1495
    global->type = JMM_VMGLOBAL_TYPE_JLONG;
1496
  } else if (flag->is_ccstr()) {
1497
    Handle str = java_lang_String::create_from_str(flag->get_ccstr(), CHECK_false);
1498
    global->value.l = (jobject)JNIHandles::make_local(THREAD, str());
1499
    global->type = JMM_VMGLOBAL_TYPE_JSTRING;
1500
  } else {
1501
    global->type = JMM_VMGLOBAL_TYPE_UNKNOWN;
1502
    return false;
1503
  }
1504

1505
  global->writeable = flag->is_writeable();
1506
  global->external = flag->is_external();
1507
  switch (flag->get_origin()) {
1508
    case JVMFlagOrigin::DEFAULT:
1509
      global->origin = JMM_VMGLOBAL_ORIGIN_DEFAULT;
1510
      break;
1511
    case JVMFlagOrigin::COMMAND_LINE:
1512
      global->origin = JMM_VMGLOBAL_ORIGIN_COMMAND_LINE;
1513
      break;
1514
    case JVMFlagOrigin::ENVIRON_VAR:
1515
      global->origin = JMM_VMGLOBAL_ORIGIN_ENVIRON_VAR;
1516
      break;
1517
    case JVMFlagOrigin::CONFIG_FILE:
1518
      global->origin = JMM_VMGLOBAL_ORIGIN_CONFIG_FILE;
1519
      break;
1520
    case JVMFlagOrigin::MANAGEMENT:
1521
      global->origin = JMM_VMGLOBAL_ORIGIN_MANAGEMENT;
1522
      break;
1523
    case JVMFlagOrigin::ERGONOMIC:
1524
      global->origin = JMM_VMGLOBAL_ORIGIN_ERGONOMIC;
1525
      break;
1526
    case JVMFlagOrigin::ATTACH_ON_DEMAND:
1527
      global->origin = JMM_VMGLOBAL_ORIGIN_ATTACH_ON_DEMAND;
1528
      break;
1529
    default:
1530
      global->origin = JMM_VMGLOBAL_ORIGIN_OTHER;
1531
  }
1532

1533
  return true;
1534
}
1535

1536
// Fill globals array of count length with jmmVMGlobal entries
1537
// specified by names. If names == null, fill globals array
1538
// with all Flags. Return value is number of entries
1539
// created in globals.
1540
// If a JVMFlag with a given name in an array element does not
1541
// exist, globals[i].name will be set to null.
1542
JVM_ENTRY(jint, jmm_GetVMGlobals(JNIEnv *env,
1543
                                 jobjectArray names,
1544
                                 jmmVMGlobal *globals,
1545
                                 jint count))
1546

1547

1548
  if (globals == nullptr) {
1549
    THROW_(vmSymbols::java_lang_NullPointerException(), 0);
1550
  }
1551

1552
  ResourceMark rm(THREAD);
1553

1554
  if (names != nullptr) {
1555
    // return the requested globals
1556
    objArrayOop ta = objArrayOop(JNIHandles::resolve_non_null(names));
1557
    objArrayHandle names_ah(THREAD, ta);
1558
    // Make sure we have a String array
1559
    Klass* element_klass = ObjArrayKlass::cast(names_ah->klass())->element_klass();
1560
    if (element_klass != vmClasses::String_klass()) {
1561
      THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(),
1562
                 "Array element type is not String class", 0);
1563
    }
1564

1565
    int names_length = names_ah->length();
1566
    int num_entries = 0;
1567
    for (int i = 0; i < names_length && i < count; i++) {
1568
      oop s = names_ah->obj_at(i);
1569
      if (s == nullptr) {
1570
        THROW_(vmSymbols::java_lang_NullPointerException(), 0);
1571
      }
1572

1573
      Handle sh(THREAD, s);
1574
      char* str = java_lang_String::as_utf8_string(s);
1575
      JVMFlag* flag = JVMFlag::find_flag(str);
1576
      if (flag != nullptr &&
1577
          add_global_entry(sh, &globals[i], flag, THREAD)) {
1578
        num_entries++;
1579
      } else {
1580
        globals[i].name = nullptr;
1581
      }
1582
    }
1583
    return num_entries;
1584
  } else {
1585
    // return all globals if names == null
1586

1587
    // last flag entry is always null, so subtract 1
1588
    int nFlags = (int) JVMFlag::numFlags - 1;
1589
    Handle null_h;
1590
    int num_entries = 0;
1591
    for (int i = 0; i < nFlags && num_entries < count;  i++) {
1592
      JVMFlag* flag = &JVMFlag::flags[i];
1593
      // Exclude develop flags in product builds.
1594
      if (flag->is_constant_in_binary()) {
1595
        continue;
1596
      }
1597
      // Exclude the locked (diagnostic, experimental) flags
1598
      if ((flag->is_unlocked() || flag->is_unlocker()) &&
1599
          add_global_entry(null_h, &globals[num_entries], flag, THREAD)) {
1600
        num_entries++;
1601
      }
1602
    }
1603
    return num_entries;
1604
  }
1605
JVM_END
1606

1607
JVM_ENTRY(void, jmm_SetVMGlobal(JNIEnv *env, jstring flag_name, jvalue new_value))
1608
  ResourceMark rm(THREAD);
1609

1610
  oop fn = JNIHandles::resolve_external_guard(flag_name);
1611
  if (fn == nullptr) {
1612
    THROW_MSG(vmSymbols::java_lang_NullPointerException(),
1613
              "The flag name cannot be null.");
1614
  }
1615
  char* name = java_lang_String::as_utf8_string(fn);
1616

1617
  FormatBuffer<80> error_msg("%s", "");
1618
  int succeed = WriteableFlags::set_flag(name, new_value, JVMFlagOrigin::MANAGEMENT, error_msg);
1619

1620
  if (succeed != JVMFlag::SUCCESS) {
1621
    if (succeed == JVMFlag::MISSING_VALUE) {
1622
      // missing value causes NPE to be thrown
1623
      THROW(vmSymbols::java_lang_NullPointerException());
1624
    } else {
1625
      // all the other errors are reported as IAE with the appropriate error message
1626
      THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
1627
                error_msg.buffer());
1628
    }
1629
  }
1630
  assert(succeed == JVMFlag::SUCCESS, "Setting flag should succeed");
1631
JVM_END
1632

1633
class ThreadTimesClosure: public ThreadClosure {
1634
 private:
1635
  objArrayHandle _names_strings;
1636
  char **_names_chars;
1637
  typeArrayHandle _times;
1638
  int _names_len;
1639
  int _times_len;
1640
  int _count;
1641

1642
 public:
1643
  ThreadTimesClosure(objArrayHandle names, typeArrayHandle times);
1644
  ~ThreadTimesClosure();
1645
  virtual void do_thread(Thread* thread);
1646
  void do_unlocked(TRAPS);
1647
  int count() { return _count; }
1648
};
1649

1650
ThreadTimesClosure::ThreadTimesClosure(objArrayHandle names,
1651
                                       typeArrayHandle times) {
1652
  assert(names() != nullptr, "names was null");
1653
  assert(times() != nullptr, "times was null");
1654
  _names_strings = names;
1655
  _names_len = names->length();
1656
  _names_chars = NEW_C_HEAP_ARRAY(char*, _names_len, mtInternal);
1657
  _times = times;
1658
  _times_len = times->length();
1659
  _count = 0;
1660
}
1661

1662
//
1663
// Called with Threads_lock held
1664
//
1665
void ThreadTimesClosure::do_thread(Thread* thread) {
1666
  assert(Threads_lock->owned_by_self(), "Must hold Threads_lock");
1667
  assert(thread != nullptr, "thread was null");
1668

1669
  // exclude externally visible JavaThreads
1670
  if (thread->is_Java_thread() && !thread->is_hidden_from_external_view()) {
1671
    return;
1672
  }
1673

1674
  if (_count >= _names_len || _count >= _times_len) {
1675
    // skip if the result array is not big enough
1676
    return;
1677
  }
1678

1679
  ResourceMark rm; // thread->name() uses ResourceArea
1680

1681
  assert(thread->name() != nullptr, "All threads should have a name");
1682
  _names_chars[_count] = os::strdup_check_oom(thread->name());
1683
  _times->long_at_put(_count, os::is_thread_cpu_time_supported() ?
1684
                        os::thread_cpu_time(thread) : -1);
1685
  _count++;
1686
}
1687

1688
// Called without Threads_lock, we can allocate String objects.
1689
void ThreadTimesClosure::do_unlocked(TRAPS) {
1690

1691
  for (int i = 0; i < _count; i++) {
1692
    Handle s = java_lang_String::create_from_str(_names_chars[i],  CHECK);
1693
    _names_strings->obj_at_put(i, s());
1694
  }
1695
}
1696

1697
ThreadTimesClosure::~ThreadTimesClosure() {
1698
  for (int i = 0; i < _count; i++) {
1699
    os::free(_names_chars[i]);
1700
  }
1701
  FREE_C_HEAP_ARRAY(char *, _names_chars);
1702
}
1703

1704
// Fills names with VM internal thread names and times with the corresponding
1705
// CPU times.  If names or times is null, a NullPointerException is thrown.
1706
// If the element type of names is not String, an IllegalArgumentException is
1707
// thrown.
1708
// If an array is not large enough to hold all the entries, only the entries
1709
// that fit will be returned.  Return value is the number of VM internal
1710
// threads entries.
1711
JVM_ENTRY(jint, jmm_GetInternalThreadTimes(JNIEnv *env,
1712
                                           jobjectArray names,
1713
                                           jlongArray times))
1714
  if (names == nullptr || times == nullptr) {
1715
     THROW_(vmSymbols::java_lang_NullPointerException(), 0);
1716
  }
1717
  objArrayOop na = objArrayOop(JNIHandles::resolve_non_null(names));
1718
  objArrayHandle names_ah(THREAD, na);
1719

1720
  // Make sure we have a String array
1721
  Klass* element_klass = ObjArrayKlass::cast(names_ah->klass())->element_klass();
1722
  if (element_klass != vmClasses::String_klass()) {
1723
    THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(),
1724
               "Array element type is not String class", 0);
1725
  }
1726

1727
  typeArrayOop ta = typeArrayOop(JNIHandles::resolve_non_null(times));
1728
  typeArrayHandle times_ah(THREAD, ta);
1729

1730
  ThreadTimesClosure ttc(names_ah, times_ah);
1731
  {
1732
    MutexLocker ml(THREAD, Threads_lock);
1733
    Threads::threads_do(&ttc);
1734
  }
1735
  ttc.do_unlocked(THREAD);
1736
  return ttc.count();
1737
JVM_END
1738

1739
static Handle find_deadlocks(bool object_monitors_only, TRAPS) {
1740
  ResourceMark rm(THREAD);
1741

1742
  VM_FindDeadlocks op(!object_monitors_only /* also check concurrent locks? */);
1743
  VMThread::execute(&op);
1744

1745
  DeadlockCycle* deadlocks = op.result();
1746
  if (deadlocks == nullptr) {
1747
    // no deadlock found and return
1748
    return Handle();
1749
  }
1750

1751
  int num_threads = 0;
1752
  DeadlockCycle* cycle;
1753
  for (cycle = deadlocks; cycle != nullptr; cycle = cycle->next()) {
1754
    num_threads += cycle->num_threads();
1755
  }
1756

1757
  objArrayOop r = oopFactory::new_objArray(vmClasses::Thread_klass(), num_threads, CHECK_NH);
1758
  objArrayHandle threads_ah(THREAD, r);
1759

1760
  int index = 0;
1761
  for (cycle = deadlocks; cycle != nullptr; cycle = cycle->next()) {
1762
    GrowableArray<JavaThread*>* deadlock_threads = cycle->threads();
1763
    int len = deadlock_threads->length();
1764
    for (int i = 0; i < len; i++) {
1765
      threads_ah->obj_at_put(index, deadlock_threads->at(i)->threadObj());
1766
      index++;
1767
    }
1768
  }
1769
  return threads_ah;
1770
}
1771

1772
// Finds cycles of threads that are deadlocked involved in object monitors
1773
// and JSR-166 synchronizers.
1774
// Returns an array of Thread objects which are in deadlock, if any.
1775
// Otherwise, returns null.
1776
//
1777
// Input parameter:
1778
//    object_monitors_only - if true, only check object monitors
1779
//
1780
JVM_ENTRY(jobjectArray, jmm_FindDeadlockedThreads(JNIEnv *env, jboolean object_monitors_only))
1781
  Handle result = find_deadlocks(object_monitors_only != 0, CHECK_NULL);
1782
  return (jobjectArray) JNIHandles::make_local(THREAD, result());
1783
JVM_END
1784

1785
// Finds cycles of threads that are deadlocked on monitor locks
1786
// Returns an array of Thread objects which are in deadlock, if any.
1787
// Otherwise, returns null.
1788
JVM_ENTRY(jobjectArray, jmm_FindMonitorDeadlockedThreads(JNIEnv *env))
1789
  Handle result = find_deadlocks(true, CHECK_NULL);
1790
  return (jobjectArray) JNIHandles::make_local(THREAD, result());
1791
JVM_END
1792

1793
// Gets the information about GC extension attributes including
1794
// the name of the attribute, its type, and a short description.
1795
//
1796
// Input parameters:
1797
//   mgr   - GC memory manager
1798
//   info  - caller allocated array of jmmExtAttributeInfo
1799
//   count - number of elements of the info array
1800
//
1801
// Returns the number of GC extension attributes filled in the info array; or
1802
// -1 if info is not big enough
1803
//
1804
JVM_ENTRY(jint, jmm_GetGCExtAttributeInfo(JNIEnv *env, jobject mgr, jmmExtAttributeInfo* info, jint count))
1805
  // All GC memory managers have 1 attribute (number of GC threads)
1806
  if (count == 0) {
1807
    return 0;
1808
  }
1809

1810
  if (info == nullptr) {
1811
   THROW_(vmSymbols::java_lang_NullPointerException(), 0);
1812
  }
1813

1814
  info[0].name = "GcThreadCount";
1815
  info[0].type = 'I';
1816
  info[0].description = "Number of GC threads";
1817
  return 1;
1818
JVM_END
1819

1820
// verify the given array is an array of java/lang/management/MemoryUsage objects
1821
// of a given length and return the objArrayOop
1822
static objArrayOop get_memory_usage_objArray(jobjectArray array, int length, TRAPS) {
1823
  if (array == nullptr) {
1824
    THROW_(vmSymbols::java_lang_NullPointerException(), 0);
1825
  }
1826

1827
  objArrayOop oa = objArrayOop(JNIHandles::resolve_non_null(array));
1828
  objArrayHandle array_h(THREAD, oa);
1829

1830
  // array must be of the given length
1831
  if (length != array_h->length()) {
1832
    THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(),
1833
               "The length of the given MemoryUsage array does not match the number of memory pools.", 0);
1834
  }
1835

1836
  // check if the element of array is of type MemoryUsage class
1837
  Klass* usage_klass = Management::java_lang_management_MemoryUsage_klass(CHECK_NULL);
1838
  Klass* element_klass = ObjArrayKlass::cast(array_h->klass())->element_klass();
1839
  if (element_klass != usage_klass) {
1840
    THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(),
1841
               "The element type is not MemoryUsage class", 0);
1842
  }
1843

1844
  return array_h();
1845
}
1846

1847
// Gets the statistics of the last GC of a given GC memory manager.
1848
// Input parameters:
1849
//   obj     - GarbageCollectorMXBean object
1850
//   gc_stat - caller allocated jmmGCStat where:
1851
//     a. before_gc_usage - array of MemoryUsage objects
1852
//     b. after_gc_usage  - array of MemoryUsage objects
1853
//     c. gc_ext_attributes_values_size is set to the
1854
//        gc_ext_attribute_values array allocated
1855
//     d. gc_ext_attribute_values is a caller allocated array of jvalue.
1856
//
1857
// On return,
1858
//   gc_index == 0 indicates no GC statistics available
1859
//
1860
//   before_gc_usage and after_gc_usage - filled with per memory pool
1861
//      before and after GC usage in the same order as the memory pools
1862
//      returned by GetMemoryPools for a given GC memory manager.
1863
//   num_gc_ext_attributes indicates the number of elements in
1864
//      the gc_ext_attribute_values array is filled; or
1865
//      -1 if the gc_ext_attributes_values array is not big enough
1866
//
1867
JVM_ENTRY(void, jmm_GetLastGCStat(JNIEnv *env, jobject obj, jmmGCStat *gc_stat))
1868
  ResourceMark rm(THREAD);
1869

1870
  if (gc_stat->gc_ext_attribute_values_size > 0 && gc_stat->gc_ext_attribute_values == nullptr) {
1871
    THROW(vmSymbols::java_lang_NullPointerException());
1872
  }
1873

1874
  // Get the GCMemoryManager
1875
  GCMemoryManager* mgr = get_gc_memory_manager_from_jobject(obj, CHECK);
1876

1877
  // Make a copy of the last GC statistics
1878
  // GC may occur while constructing the last GC information
1879
  int num_pools = MemoryService::num_memory_pools();
1880
  GCStatInfo stat(num_pools);
1881
  if (mgr->get_last_gc_stat(&stat) == 0) {
1882
    gc_stat->gc_index = 0;
1883
    return;
1884
  }
1885

1886
  gc_stat->gc_index = stat.gc_index();
1887
  gc_stat->start_time = Management::ticks_to_ms(stat.start_time());
1888
  gc_stat->end_time = Management::ticks_to_ms(stat.end_time());
1889

1890
  // Current implementation does not have GC extension attributes
1891
  gc_stat->num_gc_ext_attributes = 0;
1892

1893
  // Fill the arrays of MemoryUsage objects with before and after GC
1894
  // per pool memory usage
1895
  objArrayOop bu = get_memory_usage_objArray(gc_stat->usage_before_gc,
1896
                                             num_pools,
1897
                                             CHECK);
1898
  objArrayHandle usage_before_gc_ah(THREAD, bu);
1899

1900
  objArrayOop au = get_memory_usage_objArray(gc_stat->usage_after_gc,
1901
                                             num_pools,
1902
                                             CHECK);
1903
  objArrayHandle usage_after_gc_ah(THREAD, au);
1904

1905
  for (int i = 0; i < num_pools; i++) {
1906
    Handle before_usage = MemoryService::create_MemoryUsage_obj(stat.before_gc_usage_for_pool(i), CHECK);
1907
    Handle after_usage;
1908

1909
    MemoryUsage u = stat.after_gc_usage_for_pool(i);
1910
    if (u.max_size() == 0 && u.used() > 0) {
1911
      // If max size == 0, this pool is a survivor space.
1912
      // Set max size = -1 since the pools will be swapped after GC.
1913
      MemoryUsage usage(u.init_size(), u.used(), u.committed(), MemoryUsage::undefined_size());
1914
      after_usage = MemoryService::create_MemoryUsage_obj(usage, CHECK);
1915
    } else {
1916
      after_usage = MemoryService::create_MemoryUsage_obj(stat.after_gc_usage_for_pool(i), CHECK);
1917
    }
1918
    usage_before_gc_ah->obj_at_put(i, before_usage());
1919
    usage_after_gc_ah->obj_at_put(i, after_usage());
1920
  }
1921

1922
  if (gc_stat->gc_ext_attribute_values_size > 0) {
1923
    // Current implementation only has 1 attribute (number of GC threads)
1924
    // The type is 'I'
1925
    gc_stat->gc_ext_attribute_values[0].i = mgr->num_gc_threads();
1926
  }
1927
JVM_END
1928

1929
JVM_ENTRY(void, jmm_SetGCNotificationEnabled(JNIEnv *env, jobject obj, jboolean enabled))
1930
  ResourceMark rm(THREAD);
1931
  // Get the GCMemoryManager
1932
  GCMemoryManager* mgr = get_gc_memory_manager_from_jobject(obj, CHECK);
1933
  mgr->set_notification_enabled(enabled?true:false);
1934
JVM_END
1935

1936
// Dump heap - Returns 0 if succeeds.
1937
JVM_ENTRY(jint, jmm_DumpHeap0(JNIEnv *env, jstring outputfile, jboolean live))
1938
#if INCLUDE_SERVICES
1939
  ResourceMark rm(THREAD);
1940
  oop on = JNIHandles::resolve_external_guard(outputfile);
1941
  if (on == nullptr) {
1942
    THROW_MSG_(vmSymbols::java_lang_NullPointerException(),
1943
               "Output file name cannot be null.", -1);
1944
  }
1945
  Handle onhandle(THREAD, on);
1946
  char* name = java_lang_String::as_platform_dependent_str(onhandle, CHECK_(-1));
1947
  if (name == nullptr) {
1948
    THROW_MSG_(vmSymbols::java_lang_NullPointerException(),
1949
               "Output file name cannot be null.", -1);
1950
  }
1951
  HeapDumper dumper(live ? true : false);
1952
  if (dumper.dump(name) != 0) {
1953
    const char* errmsg = dumper.error_as_C_string();
1954
    THROW_MSG_(vmSymbols::java_io_IOException(), errmsg, -1);
1955
  }
1956
  return 0;
1957
#else  // INCLUDE_SERVICES
1958
  return -1;
1959
#endif // INCLUDE_SERVICES
1960
JVM_END
1961

1962
JVM_ENTRY(jobjectArray, jmm_GetDiagnosticCommands(JNIEnv *env))
1963
  ResourceMark rm(THREAD);
1964
  GrowableArray<const char *>* dcmd_list = DCmdFactory::DCmd_list(DCmd_Source_MBean);
1965
  objArrayOop cmd_array_oop = oopFactory::new_objArray(vmClasses::String_klass(),
1966
          dcmd_list->length(), CHECK_NULL);
1967
  objArrayHandle cmd_array(THREAD, cmd_array_oop);
1968
  for (int i = 0; i < dcmd_list->length(); i++) {
1969
    oop cmd_name = java_lang_String::create_oop_from_str(dcmd_list->at(i), CHECK_NULL);
1970
    cmd_array->obj_at_put(i, cmd_name);
1971
  }
1972
  return (jobjectArray) JNIHandles::make_local(THREAD, cmd_array());
1973
JVM_END
1974

1975
JVM_ENTRY(void, jmm_GetDiagnosticCommandInfo(JNIEnv *env, jobjectArray cmds,
1976
          dcmdInfo* infoArray))
1977
  if (cmds == nullptr || infoArray == nullptr) {
1978
    THROW(vmSymbols::java_lang_NullPointerException());
1979
  }
1980

1981
  ResourceMark rm(THREAD);
1982

1983
  objArrayOop ca = objArrayOop(JNIHandles::resolve_non_null(cmds));
1984
  objArrayHandle cmds_ah(THREAD, ca);
1985

1986
  // Make sure we have a String array
1987
  Klass* element_klass = ObjArrayKlass::cast(cmds_ah->klass())->element_klass();
1988
  if (element_klass != vmClasses::String_klass()) {
1989
    THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
1990
               "Array element type is not String class");
1991
  }
1992

1993
  GrowableArray<DCmdInfo *>* info_list = DCmdFactory::DCmdInfo_list(DCmd_Source_MBean);
1994

1995
  int num_cmds = cmds_ah->length();
1996
  for (int i = 0; i < num_cmds; i++) {
1997
    oop cmd = cmds_ah->obj_at(i);
1998
    if (cmd == nullptr) {
1999
        THROW_MSG(vmSymbols::java_lang_NullPointerException(),
2000
                "Command name cannot be null.");
2001
    }
2002
    char* cmd_name = java_lang_String::as_utf8_string(cmd);
2003
    if (cmd_name == nullptr) {
2004
        THROW_MSG(vmSymbols::java_lang_NullPointerException(),
2005
                "Command name cannot be null.");
2006
    }
2007
    int pos = info_list->find_if([&](DCmdInfo* info) {
2008
      return info->name_equals(cmd_name);
2009
    });
2010
    if (pos == -1) {
2011
        THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
2012
             "Unknown diagnostic command");
2013
    }
2014
    DCmdInfo* info = info_list->at(pos);
2015
    infoArray[i].name = info->name();
2016
    infoArray[i].description = info->description();
2017
    infoArray[i].impact = info->impact();
2018
    JavaPermission p = info->permission();
2019
    infoArray[i].permission_class = p._class;
2020
    infoArray[i].permission_name = p._name;
2021
    infoArray[i].permission_action = p._action;
2022
    infoArray[i].num_arguments = info->num_arguments();
2023
    infoArray[i].enabled = info->is_enabled();
2024
  }
2025
JVM_END
2026

2027
JVM_ENTRY(void, jmm_GetDiagnosticCommandArgumentsInfo(JNIEnv *env,
2028
          jstring command, dcmdArgInfo* infoArray, jint count))
2029
  ResourceMark rm(THREAD);
2030
  oop cmd = JNIHandles::resolve_external_guard(command);
2031
  if (cmd == nullptr) {
2032
    THROW_MSG(vmSymbols::java_lang_NullPointerException(),
2033
              "Command line cannot be null.");
2034
  }
2035
  char* cmd_name = java_lang_String::as_utf8_string(cmd);
2036
  if (cmd_name == nullptr) {
2037
    THROW_MSG(vmSymbols::java_lang_NullPointerException(),
2038
              "Command line content cannot be null.");
2039
  }
2040
  DCmd* dcmd = nullptr;
2041
  DCmdFactory*factory = DCmdFactory::factory(DCmd_Source_MBean, cmd_name,
2042
                                             strlen(cmd_name));
2043
  if (factory != nullptr) {
2044
    dcmd = factory->create_resource_instance(nullptr);
2045
  }
2046
  if (dcmd == nullptr) {
2047
    THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
2048
              "Unknown diagnostic command");
2049
  }
2050
  DCmdMark mark(dcmd);
2051
  GrowableArray<DCmdArgumentInfo*>* array = dcmd->argument_info_array();
2052
  const int num_args = array->length();
2053
  if (num_args != count) {
2054
    assert(false, "jmm_GetDiagnosticCommandArgumentsInfo count mismatch (%d vs %d)", count, num_args);
2055
    THROW_MSG(vmSymbols::java_lang_InternalError(), "jmm_GetDiagnosticCommandArgumentsInfo count mismatch");
2056
  }
2057
  for (int i = 0; i < num_args; i++) {
2058
    infoArray[i].name = array->at(i)->name();
2059
    infoArray[i].description = array->at(i)->description();
2060
    infoArray[i].type = array->at(i)->type();
2061
    infoArray[i].default_string = array->at(i)->default_string();
2062
    infoArray[i].mandatory = array->at(i)->is_mandatory();
2063
    infoArray[i].option = array->at(i)->is_option();
2064
    infoArray[i].multiple = array->at(i)->is_multiple();
2065
    infoArray[i].position = array->at(i)->position();
2066
  }
2067
  return;
2068
JVM_END
2069

2070
JVM_ENTRY(jstring, jmm_ExecuteDiagnosticCommand(JNIEnv *env, jstring commandline))
2071
  ResourceMark rm(THREAD);
2072
  oop cmd = JNIHandles::resolve_external_guard(commandline);
2073
  if (cmd == nullptr) {
2074
    THROW_MSG_NULL(vmSymbols::java_lang_NullPointerException(),
2075
                   "Command line cannot be null.");
2076
  }
2077
  char* cmdline = java_lang_String::as_utf8_string(cmd);
2078
  if (cmdline == nullptr) {
2079
    THROW_MSG_NULL(vmSymbols::java_lang_NullPointerException(),
2080
                   "Command line content cannot be null.");
2081
  }
2082
  bufferedStream output;
2083
  DCmd::parse_and_execute(DCmd_Source_MBean, &output, cmdline, ' ', CHECK_NULL);
2084
  oop result = java_lang_String::create_oop_from_str(output.as_string(), CHECK_NULL);
2085
  return (jstring) JNIHandles::make_local(THREAD, result);
2086
JVM_END
2087

2088
JVM_ENTRY(void, jmm_SetDiagnosticFrameworkNotificationEnabled(JNIEnv *env, jboolean enabled))
2089
  DCmdFactory::set_jmx_notification_enabled(enabled?true:false);
2090
JVM_END
2091

2092
jlong Management::ticks_to_ms(jlong ticks) {
2093
  assert(os::elapsed_frequency() > 0, "Must be non-zero");
2094
  return (jlong)(((double)ticks / (double)os::elapsed_frequency())
2095
                 * (double)1000.0);
2096
}
2097

2098
// Gets the amount of memory allocated on the Java heap since JVM launch.
2099
JVM_ENTRY(jlong, jmm_GetTotalThreadAllocatedMemory(JNIEnv *env))
2100
    // A thread increments exited_allocated_bytes in ThreadService::remove_thread
2101
    // only after it removes itself from the threads list, and once a TLH is
2102
    // created, no thread it references can remove itself from the threads
2103
    // list, so none can update exited_allocated_bytes. We therefore initialize
2104
    // result with exited_allocated_bytes after after we create the TLH so that
2105
    // the final result can only be short due to (1) threads that start after
2106
    // the TLH is created, or (2) terminating threads that escape TLH creation
2107
    // and don't update exited_allocated_bytes before we initialize result.
2108

2109
    // We keep a high water mark to ensure monotonicity in case threads counted
2110
    // on a previous call end up in state (2).
2111
    static jlong high_water_result = 0;
2112

2113
    JavaThreadIteratorWithHandle jtiwh;
2114
    jlong result = ThreadService::exited_allocated_bytes();
2115
    for (; JavaThread* thread = jtiwh.next();) {
2116
      jlong size = thread->cooked_allocated_bytes();
2117
      result += size;
2118
    }
2119

2120
    {
2121
      assert(MonitoringSupport_lock != nullptr, "Must be");
2122
      MutexLocker ml(MonitoringSupport_lock, Mutex::_no_safepoint_check_flag);
2123
      if (result < high_water_result) {
2124
        // Encountered (2) above, or result wrapped to a negative value. In
2125
        // the latter case, it's pegged at the last positive value.
2126
        result = high_water_result;
2127
      } else {
2128
        high_water_result = result;
2129
      }
2130
    }
2131
    return result;
2132
JVM_END
2133

2134
// Gets the amount of memory allocated on the Java heap for a single thread.
2135
// Returns -1 if the thread does not exist or has terminated.
2136
JVM_ENTRY(jlong, jmm_GetOneThreadAllocatedMemory(JNIEnv *env, jlong thread_id))
2137
  if (thread_id < 0) {
2138
    THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(),
2139
               "Invalid thread ID", -1);
2140
  }
2141

2142
  if (thread_id == 0) { // current thread
2143
    return thread->cooked_allocated_bytes();
2144
  }
2145

2146
  ThreadsListHandle tlh;
2147
  JavaThread* java_thread = tlh.list()->find_JavaThread_from_java_tid(thread_id);
2148
  if (is_platform_thread(java_thread)) {
2149
    return java_thread->cooked_allocated_bytes();
2150
  }
2151
  return -1;
2152
JVM_END
2153

2154
// Gets an array containing the amount of memory allocated on the Java
2155
// heap for a set of threads (in bytes).  Each element of the array is
2156
// the amount of memory allocated for the thread ID specified in the
2157
// corresponding entry in the given array of thread IDs; or -1 if the
2158
// thread does not exist or has terminated.
2159
JVM_ENTRY(void, jmm_GetThreadAllocatedMemory(JNIEnv *env, jlongArray ids,
2160
                                             jlongArray sizeArray))
2161
  // Check if threads is null
2162
  if (ids == nullptr || sizeArray == nullptr) {
2163
    THROW(vmSymbols::java_lang_NullPointerException());
2164
  }
2165

2166
  ResourceMark rm(THREAD);
2167
  typeArrayOop ta = typeArrayOop(JNIHandles::resolve_non_null(ids));
2168
  typeArrayHandle ids_ah(THREAD, ta);
2169

2170
  typeArrayOop sa = typeArrayOop(JNIHandles::resolve_non_null(sizeArray));
2171
  typeArrayHandle sizeArray_h(THREAD, sa);
2172

2173
  // validate the thread id array
2174
  validate_thread_id_array(ids_ah, CHECK);
2175

2176
  // sizeArray must be of the same length as the given array of thread IDs
2177
  int num_threads = ids_ah->length();
2178
  if (num_threads != sizeArray_h->length()) {
2179
    THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
2180
              "The length of the given long array does not match the length of "
2181
              "the given array of thread IDs");
2182
  }
2183

2184
  ThreadsListHandle tlh;
2185
  for (int i = 0; i < num_threads; i++) {
2186
    JavaThread* java_thread = tlh.list()->find_JavaThread_from_java_tid(ids_ah->long_at(i));
2187
    if (is_platform_thread(java_thread)) {
2188
      sizeArray_h->long_at_put(i, java_thread->cooked_allocated_bytes());
2189
    }
2190
  }
2191
JVM_END
2192

2193
// Returns the CPU time consumed by a given thread (in nanoseconds).
2194
// If thread_id == 0, CPU time for the current thread is returned.
2195
// If user_sys_cpu_time = true, user level and system CPU time of
2196
// a given thread is returned; otherwise, only user level CPU time
2197
// is returned.
2198
JVM_ENTRY(jlong, jmm_GetThreadCpuTimeWithKind(JNIEnv *env, jlong thread_id, jboolean user_sys_cpu_time))
2199
  if (!os::is_thread_cpu_time_supported()) {
2200
    return -1;
2201
  }
2202

2203
  if (thread_id < 0) {
2204
    THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(),
2205
               "Invalid thread ID", -1);
2206
  }
2207

2208
  JavaThread* java_thread = nullptr;
2209
  if (thread_id == 0) {
2210
    // current thread
2211
    return os::current_thread_cpu_time(user_sys_cpu_time != 0);
2212
  } else {
2213
    ThreadsListHandle tlh;
2214
    java_thread = tlh.list()->find_JavaThread_from_java_tid(thread_id);
2215
    if (is_platform_thread(java_thread)) {
2216
      return os::thread_cpu_time((Thread*) java_thread, user_sys_cpu_time != 0);
2217
    }
2218
  }
2219
  return -1;
2220
JVM_END
2221

2222
// Gets an array containing the CPU times consumed by a set of threads
2223
// (in nanoseconds).  Each element of the array is the CPU time for the
2224
// thread ID specified in the corresponding entry in the given array
2225
// of thread IDs; or -1 if the thread does not exist or has terminated.
2226
// If user_sys_cpu_time = true, the sum of user level and system CPU time
2227
// for the given thread is returned; otherwise, only user level CPU time
2228
// is returned.
2229
JVM_ENTRY(void, jmm_GetThreadCpuTimesWithKind(JNIEnv *env, jlongArray ids,
2230
                                              jlongArray timeArray,
2231
                                              jboolean user_sys_cpu_time))
2232
  // Check if threads is null
2233
  if (ids == nullptr || timeArray == nullptr) {
2234
    THROW(vmSymbols::java_lang_NullPointerException());
2235
  }
2236

2237
  ResourceMark rm(THREAD);
2238
  typeArrayOop ta = typeArrayOop(JNIHandles::resolve_non_null(ids));
2239
  typeArrayHandle ids_ah(THREAD, ta);
2240

2241
  typeArrayOop tia = typeArrayOop(JNIHandles::resolve_non_null(timeArray));
2242
  typeArrayHandle timeArray_h(THREAD, tia);
2243

2244
  // validate the thread id array
2245
  validate_thread_id_array(ids_ah, CHECK);
2246

2247
  // timeArray must be of the same length as the given array of thread IDs
2248
  int num_threads = ids_ah->length();
2249
  if (num_threads != timeArray_h->length()) {
2250
    THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
2251
              "The length of the given long array does not match the length of "
2252
              "the given array of thread IDs");
2253
  }
2254

2255
  ThreadsListHandle tlh;
2256
  for (int i = 0; i < num_threads; i++) {
2257
    JavaThread* java_thread = tlh.list()->find_JavaThread_from_java_tid(ids_ah->long_at(i));
2258
    if (is_platform_thread(java_thread)) {
2259
      timeArray_h->long_at_put(i, os::thread_cpu_time((Thread*)java_thread,
2260
                                                      user_sys_cpu_time != 0));
2261
    }
2262
  }
2263
JVM_END
2264

2265
const struct jmmInterface_1_ jmm_interface = {
2266
  nullptr,
2267
  nullptr,
2268
  jmm_GetVersion,
2269
  jmm_GetOptionalSupport,
2270
  jmm_GetThreadInfo,
2271
  jmm_GetMemoryPools,
2272
  jmm_GetMemoryManagers,
2273
  jmm_GetMemoryPoolUsage,
2274
  jmm_GetPeakMemoryPoolUsage,
2275
  jmm_GetTotalThreadAllocatedMemory,
2276
  jmm_GetOneThreadAllocatedMemory,
2277
  jmm_GetThreadAllocatedMemory,
2278
  jmm_GetMemoryUsage,
2279
  jmm_GetLongAttribute,
2280
  jmm_GetBoolAttribute,
2281
  jmm_SetBoolAttribute,
2282
  jmm_GetLongAttributes,
2283
  jmm_FindMonitorDeadlockedThreads,
2284
  jmm_GetThreadCpuTime,
2285
  jmm_GetVMGlobalNames,
2286
  jmm_GetVMGlobals,
2287
  jmm_GetInternalThreadTimes,
2288
  jmm_ResetStatistic,
2289
  jmm_SetPoolSensor,
2290
  jmm_SetPoolThreshold,
2291
  jmm_GetPoolCollectionUsage,
2292
  jmm_GetGCExtAttributeInfo,
2293
  jmm_GetLastGCStat,
2294
  jmm_GetThreadCpuTimeWithKind,
2295
  jmm_GetThreadCpuTimesWithKind,
2296
  jmm_DumpHeap0,
2297
  jmm_FindDeadlockedThreads,
2298
  jmm_SetVMGlobal,
2299
  nullptr,
2300
  jmm_DumpThreads,
2301
  jmm_SetGCNotificationEnabled,
2302
  jmm_GetDiagnosticCommands,
2303
  jmm_GetDiagnosticCommandInfo,
2304
  jmm_GetDiagnosticCommandArgumentsInfo,
2305
  jmm_ExecuteDiagnosticCommand,
2306
  jmm_SetDiagnosticFrameworkNotificationEnabled
2307
};
2308
#endif // INCLUDE_MANAGEMENT
2309

2310
void* Management::get_jmm_interface(int version) {
2311
#if INCLUDE_MANAGEMENT
2312
  if (version == JMM_VERSION) {
2313
    return (void*) &jmm_interface;
2314
  }
2315
#endif // INCLUDE_MANAGEMENT
2316
  return nullptr;
2317
}
2318

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.