Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions hotspot/src/share/vm/runtime/mutexLocker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ Mutex* Shared_SATB_Q_lock = NULL;
Mutex* DirtyCardQ_FL_lock = NULL;
Monitor* DirtyCardQ_CBL_mon = NULL;
Mutex* Shared_DirtyCardQ_lock = NULL;
Mutex* MonitoringSupport_lock = NULL;
Mutex* ParGCRareEvent_lock = NULL;
Mutex* EvacFailureStack_lock = NULL;
Mutex* DerivedPointerTableGC_lock = NULL;
Expand Down Expand Up @@ -208,6 +209,8 @@ void mutex_init() {

def(StringDedupQueue_lock , Monitor, leaf, true );
def(StringDedupTable_lock , Mutex , leaf, true );

def(MonitoringSupport_lock , Mutex , leaf, true ); // used for serviceability monitoring support
}
def(ParGCRareEvent_lock , Mutex , leaf , true );
def(DerivedPointerTableGC_lock , Mutex, leaf, true );
Expand Down
3 changes: 2 additions & 1 deletion hotspot/src/share/vm/runtime/mutexLocker.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
Expand Down Expand Up @@ -101,6 +101,7 @@ extern Mutex* Shared_DirtyCardQ_lock; // Lock protecting dirty card
// queue shared by
// non-Java threads.
// (see option ExplicitGCInvokesConcurrent)
extern Mutex* MonitoringSupport_lock; // Protects updates to the serviceability memory pools and allocated memory high water mark.
extern Mutex* ParGCRareEvent_lock; // Synchronizes various (rare) parallel GC ops.
extern Mutex* EvacFailureStack_lock; // guards the evac failure scan stack
extern Mutex* Compile_lock; // a lock held when Compilation is updating code (used to block CodeCache traversal, CHA updates, etc)
Expand Down
5 changes: 3 additions & 2 deletions hotspot/src/share/vm/services/jmm.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
Expand Down Expand Up @@ -218,7 +218,8 @@ typedef struct {
} dcmdArgInfo;

typedef struct jmmInterface_1_ {
void* reserved1;
jlong (JNICALL *GetTotalThreadAllocatedMemory)
(JNIEnv *env);
jlong (JNICALL *GetOneThreadAllocatedMemory)
(JNIEnv *env,
jlong thread_id);
Expand Down
44 changes: 35 additions & 9 deletions hotspot/src/share/vm/services/management.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
#include "runtime/interfaceSupport.hpp"
#include "runtime/javaCalls.hpp"
#include "runtime/jniHandles.hpp"
#include "runtime/mutexLocker.hpp"
#include "runtime/os.hpp"
#include "runtime/serviceThread.hpp"
#include "runtime/thread.inline.hpp"
Expand Down Expand Up @@ -428,8 +429,6 @@ static MemoryPool* get_memory_pool_from_jobject(jobject obj, TRAPS) {
return MemoryService::get_memory_pool(ph);
}

#endif // INCLUDE_MANAGEMENT

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

Expand All @@ -445,8 +444,6 @@ static void validate_thread_id_array(typeArrayHandle ids_ah, TRAPS) {
}
}

#if INCLUDE_MANAGEMENT

static void validate_thread_info_array(objArrayHandle infoArray_h, TRAPS) {
// check if the element of infoArray is of type ThreadInfo class
Klass* threadinfo_klass = Management::java_lang_management_ThreadInfo_klass(CHECK);
Expand Down Expand Up @@ -2230,7 +2227,39 @@ jlong Management::ticks_to_ms(jlong ticks) {
return (jlong)(((double)ticks / (double)os::elapsed_frequency())
* (double)1000.0);
}
#endif // INCLUDE_MANAGEMENT

// Gets the amount of memory allocated on the Java heap since JVM launch.
JVM_ENTRY(jlong, jmm_GetTotalThreadAllocatedMemory(JNIEnv *env))
// We keep a high water mark to ensure monotonicity
static jlong high_water_result = 0;
static jlong prev_result = 0;

jlong result;
if (Threads_lock->try_lock()) {
result = ThreadService::exited_allocated_bytes();
for (JavaThread* tp = Threads::first(); tp != NULL; tp = tp->next()) {
jlong size = thread->cooked_allocated_bytes();
result += size;
}
Threads_lock->unlock();
} else {
// Return the previous result if Threads_lock is locked
result = prev_result;
}

{
MutexLockerEx ml(MonitoringSupport_lock, Mutex::_no_safepoint_check_flag);
if (result < high_water_result) {
// Result wrapped to a negative value, in which case it's
// pegged at the last positive value.
result = high_water_result;
} else {
high_water_result = result;
}
prev_result = result;
}
return result;
JVM_END

// Gets the amount of memory allocated on the Java heap for a single thread.
// Returns -1 if the thread does not exist or has terminated.
Expand Down Expand Up @@ -2368,11 +2397,8 @@ JVM_ENTRY(void, jmm_GetThreadCpuTimesWithKind(JNIEnv *env, jlongArray ids,
}
JVM_END



#if INCLUDE_MANAGEMENT
const struct jmmInterface_1_ jmm_interface = {
NULL,
jmm_GetTotalThreadAllocatedMemory,
jmm_GetOneThreadAllocatedMemory,
jmm_GetVersion,
jmm_GetOptionalSupport,
Expand Down
5 changes: 5 additions & 0 deletions hotspot/src/share/vm/services/threadService.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ PerfVariable* ThreadService::_daemon_threads_count = NULL;
volatile int ThreadService::_exiting_threads_count = 0;
volatile int ThreadService::_exiting_daemon_threads_count = 0;

volatile jlong ThreadService::_exited_allocated_bytes = 0;

ThreadDumpResult* ThreadService::_threaddump_list = NULL;

static const int INITIAL_ARRAY_SIZE = 10;
Expand Down Expand Up @@ -119,6 +121,9 @@ void ThreadService::add_thread(JavaThread* thread, bool daemon) {
}

void ThreadService::remove_thread(JavaThread* thread, bool daemon) {
// Include hidden thread allcations in exited_allocated_bytes
ThreadService::incr_exited_allocated_bytes(thread->cooked_allocated_bytes());

Atomic::dec((jint*) &_exiting_threads_count);

if (thread->is_hidden_from_external_view() ||
Expand Down
10 changes: 10 additions & 0 deletions hotspot/src/share/vm/services/threadService.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ class ThreadService : public AllStatic {
static PerfVariable* _peak_threads_count;
static PerfVariable* _daemon_threads_count;

static volatile jlong _exited_allocated_bytes;

// These 2 counters are atomically incremented once the thread is exiting.
// They will be atomically decremented when ThreadService::remove_thread is called.
static volatile int _exiting_threads_count;
Expand Down Expand Up @@ -95,6 +97,14 @@ class ThreadService : public AllStatic {
static int exiting_threads_count() { return _exiting_threads_count; }
static int exiting_daemon_threads_count() { return _exiting_daemon_threads_count; }

static jlong exited_allocated_bytes() { return Atomic::load(&_exited_allocated_bytes); }
static void incr_exited_allocated_bytes(jlong size) {
// No need for an atomic add because called under the Threads_lock,
// but because _exited_allocated_bytes is read concurrently, need
// atomic store to avoid readers seeing a partial update.
Atomic::store(_exited_allocated_bytes + size, &_exited_allocated_bytes);
}

// Support for thread dump
static void add_thread_dump(ThreadDumpResult* dump);
static void remove_thread_dump(ThreadDumpResult* dump);
Expand Down
1 change: 1 addition & 0 deletions jdk/make/mapfiles/libmanagement/mapfile-vers
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ SUNWprivate_1.1 {
Java_sun_management_ThreadImpl_getThreadUserCpuTime1;
Java_sun_management_ThreadImpl_getThreadAllocatedMemory0;
Java_sun_management_ThreadImpl_getThreadAllocatedMemory1;
Java_sun_management_ThreadImpl_getTotalThreadAllocatedMemory;
Java_sun_management_ThreadImpl_resetContentionTimes0;
Java_sun_management_ThreadImpl_resetPeakThreadCount0;
Java_sun_management_ThreadImpl_setThreadContentionMonitoringEnabled0;
Expand Down
36 changes: 36 additions & 0 deletions jdk/src/share/classes/com/sun/management/ThreadMXBean.java
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,42 @@ public interface ThreadMXBean extends java.lang.management.ThreadMXBean {
*/
public long[] getThreadUserTime(long[] ids);

/**
* Returns an approximation of the total amount of memory, in bytes, allocated
* in heap memory by all threads since the Java virtual machine started.
* The returned value is an approximation because some Java virtual machine
* implementations may use object allocation mechanisms that result in a
* delay between the time an object is allocated and the time its size is
* recorded.
*
* @implSpec The default implementation throws {@code UnsupportedOperationException}
* if the Java virtual machine implementation does not support thread
* memory allocation measurement, and otherwise acts as though thread
* memory allocation measurement is disabled.
*
* @return an approximation of the total memory allocated, in bytes, in
* heap memory since the Java virtual machine was started,
* if thread memory allocation measurement is enabled;
* {@code -1} otherwise.
*
* @throws UnsupportedOperationException if the Java virtual
* machine implementation does not support thread memory allocation
* measurement.
*
* @see #isThreadAllocatedMemorySupported
* @see #isThreadAllocatedMemoryEnabled
* @see #setThreadAllocatedMemoryEnabled
*
* @since 8u412
*/
public default long getTotalThreadAllocatedBytes() {
if (!isThreadAllocatedMemorySupported()) {
throw new UnsupportedOperationException(
"Thread allocated memory measurement is not supported.");
}
return -1;
}

/**
* Returns an approximation of the total amount of memory, in bytes,
* allocated in heap memory for the current thread.
Expand Down
8 changes: 8 additions & 0 deletions jdk/src/share/classes/sun/management/ThreadImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -331,6 +331,13 @@ public void setThreadCpuTimeEnabled(boolean enable) {
}
}

public long getTotalThreadAllocatedBytes() {
if (isThreadAllocatedMemoryEnabled()) {
return getTotalThreadAllocatedMemory();
}
return -1;
}

public long getCurrentThreadAllocatedBytes() {
if (isThreadAllocatedMemoryEnabled()) {
return getThreadAllocatedMemory0(0);
Expand Down Expand Up @@ -507,6 +514,7 @@ private static native void getThreadInfo1(long[] ids,
private static native void getThreadUserCpuTime1(long[] ids, long[] result);
private static native long getThreadAllocatedMemory0(long id);
private static native void getThreadAllocatedMemory1(long[] ids, long[] result);
private static native long getTotalThreadAllocatedMemory();
private static native void setThreadCpuTimeEnabled0(boolean enable);
private static native void setThreadAllocatedMemoryEnabled0(boolean enable);
private static native void setThreadContentionMonitoringEnabled0(boolean enable);
Expand Down
5 changes: 3 additions & 2 deletions jdk/src/share/javavm/export/jmm.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
Expand Down Expand Up @@ -218,7 +218,8 @@ typedef struct {
} dcmdArgInfo;

typedef struct jmmInterface_1_ {
void* reserved1;
jlong (JNICALL *GetTotalThreadAllocatedMemory)
(JNIEnv *env);
jlong (JNICALL *GetOneThreadAllocatedMemory)
(JNIEnv *env,
jlong thread_id);
Expand Down
11 changes: 9 additions & 2 deletions jdk/src/share/native/sun/management/ThreadImpl.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
Expand Down Expand Up @@ -98,7 +98,7 @@ JNIEXPORT jlong JNICALL
Java_sun_management_ThreadImpl_getThreadAllocatedMemory0
(JNIEnv *env, jclass cls, jlong tid)
{
return jmm_interface->GetOneThreadAllocatedMemory(env, tid);
return jmm_interface->GetOneThreadAllocatedMemory(env, tid);
}

JNIEXPORT void JNICALL
Expand All @@ -108,6 +108,13 @@ Java_sun_management_ThreadImpl_getThreadAllocatedMemory1
jmm_interface->GetThreadAllocatedMemory(env, ids, sizeArray);
}

JNIEXPORT jlong JNICALL
Java_sun_management_ThreadImpl_getTotalThreadAllocatedMemory
(JNIEnv *env, jclass cls)
{
return jmm_interface->GetTotalThreadAllocatedMemory(env);
}

JNIEXPORT jobjectArray JNICALL
Java_sun_management_ThreadImpl_findMonitorDeadlockedThreads0
(JNIEnv *env, jclass cls)
Expand Down
Loading