8304074: [JMX] Add an approximation of total bytes allocated on the Java heap by the JVM
Reviewed-by: dholmes, mchung
This commit is contained in:
parent
15e028530a
commit
3eced01f9e
src
hotspot/share
java.management/share
jdk.management/share/classes/com/sun/management
test/jdk/com/sun/management/ThreadMXBean
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 2020, 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
|
||||
@ -52,7 +52,8 @@ enum {
|
||||
JMM_VERSION_1_2_2 = 0x20010202,
|
||||
JMM_VERSION_2 = 0x20020000, // JDK 10
|
||||
JMM_VERSION_3 = 0x20030000, // JDK 14
|
||||
JMM_VERSION = JMM_VERSION_3
|
||||
JMM_VERSION_4 = 0x20040000, // JDK 21
|
||||
JMM_VERSION = JMM_VERSION_4
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
@ -240,6 +241,8 @@ typedef struct jmmInterface_1_ {
|
||||
jobject (JNICALL *GetMemoryPoolUsage) (JNIEnv* env, jobject pool);
|
||||
jobject (JNICALL *GetPeakMemoryPoolUsage) (JNIEnv* env, jobject pool);
|
||||
|
||||
jlong (JNICALL *GetTotalThreadAllocatedMemory)
|
||||
(JNIEnv *env);
|
||||
jlong (JNICALL *GetOneThreadAllocatedMemory)
|
||||
(JNIEnv *env,
|
||||
jlong thread_id);
|
||||
|
@ -74,7 +74,7 @@ extern Mutex* G1RareEvent_lock; // Synchronizes (rare) parallel
|
||||
extern Mutex* G1DetachedRefinementStats_lock; // Lock protecting detached refinement stats
|
||||
extern Mutex* MarkStackFreeList_lock; // Protects access to the global mark stack free list.
|
||||
extern Mutex* MarkStackChunkList_lock; // Protects access to the global mark stack chunk list.
|
||||
extern Mutex* MonitoringSupport_lock; // Protects updates to the serviceability memory pools.
|
||||
extern Mutex* MonitoringSupport_lock; // Protects updates to the serviceability memory pools and allocated memory high water mark.
|
||||
extern Monitor* ConcurrentGCBreakpoints_lock; // Protects concurrent GC breakpoint management
|
||||
extern Mutex* Compile_lock; // a lock held when Compilation is updating code (used to block CodeCache traversal, CHA updates, etc)
|
||||
extern Monitor* MethodCompileQueue_lock; // a lock held when method compilations are enqueued, dequeued
|
||||
|
@ -47,6 +47,7 @@
|
||||
#include "runtime/interfaceSupport.inline.hpp"
|
||||
#include "runtime/javaCalls.hpp"
|
||||
#include "runtime/jniHandles.inline.hpp"
|
||||
#include "runtime/mutexLocker.hpp"
|
||||
#include "runtime/notificationThread.hpp"
|
||||
#include "runtime/os.hpp"
|
||||
#include "runtime/thread.inline.hpp"
|
||||
@ -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();
|
||||
|
||||
@ -455,8 +454,6 @@ static bool is_platform_thread(JavaThread* jt) {
|
||||
}
|
||||
}
|
||||
|
||||
#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);
|
||||
@ -2095,7 +2092,41 @@ 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))
|
||||
// A thread increments exited_allocated_bytes in ThreadService::remove_thread
|
||||
// only after it removes itself from the threads list, and once a TLH is
|
||||
// created, no thread it references can remove itself from the threads
|
||||
// list, so none can update exited_allocated_bytes. We therefore initialize
|
||||
// result with exited_allocated_bytes after after we create the TLH so that
|
||||
// the final result can only be short due to (1) threads that start after
|
||||
// the TLH is created, or (2) terminating threads that escape TLH creation
|
||||
// and don't update exited_allocated_bytes before we initialize result.
|
||||
|
||||
// We keep a high water mark to ensure monotonicity in case threads counted
|
||||
// on a previous call end up in state (2).
|
||||
static jlong high_water_result = 0;
|
||||
|
||||
JavaThreadIteratorWithHandle jtiwh;
|
||||
jlong result = ThreadService::exited_allocated_bytes();
|
||||
for (; JavaThread* thread = jtiwh.next();) {
|
||||
jlong size = thread->cooked_allocated_bytes();
|
||||
result += size;
|
||||
}
|
||||
|
||||
{
|
||||
MutexLocker ml(MonitoringSupport_lock, Mutex::_no_safepoint_check_flag);
|
||||
if (result < high_water_result) {
|
||||
// Encountered (2) above, or result wrapped to a negative value. In
|
||||
// the latter case, it's pegged at the last positive value.
|
||||
result = high_water_result;
|
||||
} else {
|
||||
high_water_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.
|
||||
@ -2228,9 +2259,6 @@ JVM_ENTRY(void, jmm_GetThreadCpuTimesWithKind(JNIEnv *env, jlongArray ids,
|
||||
}
|
||||
JVM_END
|
||||
|
||||
|
||||
|
||||
#if INCLUDE_MANAGEMENT
|
||||
const struct jmmInterface_1_ jmm_interface = {
|
||||
nullptr,
|
||||
nullptr,
|
||||
@ -2241,6 +2269,7 @@ const struct jmmInterface_1_ jmm_interface = {
|
||||
jmm_GetMemoryManagers,
|
||||
jmm_GetMemoryPoolUsage,
|
||||
jmm_GetPeakMemoryPoolUsage,
|
||||
jmm_GetTotalThreadAllocatedMemory,
|
||||
jmm_GetOneThreadAllocatedMemory,
|
||||
jmm_GetThreadAllocatedMemory,
|
||||
jmm_GetMemoryUsage,
|
||||
|
@ -45,6 +45,7 @@
|
||||
#include "runtime/init.hpp"
|
||||
#include "runtime/javaThread.inline.hpp"
|
||||
#include "runtime/objectMonitor.inline.hpp"
|
||||
#include "runtime/thread.inline.hpp"
|
||||
#include "runtime/threads.hpp"
|
||||
#include "runtime/threadSMR.inline.hpp"
|
||||
#include "runtime/vframe.hpp"
|
||||
@ -70,6 +71,8 @@ PerfVariable* ThreadService::_daemon_threads_count = nullptr;
|
||||
volatile int ThreadService::_atomic_threads_count = 0;
|
||||
volatile int ThreadService::_atomic_daemon_threads_count = 0;
|
||||
|
||||
volatile jlong ThreadService::_exited_allocated_bytes = 0;
|
||||
|
||||
ThreadDumpResult* ThreadService::_threaddump_list = nullptr;
|
||||
|
||||
static const int INITIAL_ARRAY_SIZE = 10;
|
||||
@ -157,6 +160,9 @@ void ThreadService::decrement_thread_counts(JavaThread* jt, bool daemon) {
|
||||
void ThreadService::remove_thread(JavaThread* thread, bool daemon) {
|
||||
assert(Threads_lock->owned_by_self(), "must have threads lock");
|
||||
|
||||
// Include hidden thread allcations in exited_allocated_bytes
|
||||
ThreadService::incr_exited_allocated_bytes(thread->cooked_allocated_bytes());
|
||||
|
||||
// Do not count hidden threads
|
||||
if (is_hidden_thread(thread)) {
|
||||
return;
|
||||
|
@ -61,6 +61,10 @@ private:
|
||||
static PerfVariable* _peak_threads_count;
|
||||
static PerfVariable* _daemon_threads_count;
|
||||
|
||||
// As could this...
|
||||
// Number of heap bytes allocated by terminated threads.
|
||||
static volatile jlong _exited_allocated_bytes;
|
||||
|
||||
// These 2 counters are like the above thread counts, but are
|
||||
// atomically decremented in ThreadService::current_thread_exiting instead of
|
||||
// ThreadService::remove_thread, so that the thread count is updated before
|
||||
@ -102,6 +106,14 @@ public:
|
||||
static jlong get_live_thread_count() { return _atomic_threads_count; }
|
||||
static jlong get_daemon_thread_count() { return _atomic_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, _exited_allocated_bytes + size);
|
||||
}
|
||||
|
||||
// Support for thread dump
|
||||
static void add_thread_dump(ThreadDumpResult* dump);
|
||||
static void remove_thread_dump(ThreadDumpResult* dump);
|
||||
|
@ -342,6 +342,13 @@ public class ThreadImpl implements ThreadMXBean {
|
||||
}
|
||||
}
|
||||
|
||||
protected long getTotalThreadAllocatedBytes() {
|
||||
if (isThreadAllocatedMemoryEnabled()) {
|
||||
return getTotalThreadAllocatedMemory();
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
protected long getCurrentThreadAllocatedBytes() {
|
||||
if (isThreadAllocatedMemoryEnabled() && !Thread.currentThread().isVirtual()) {
|
||||
return getThreadAllocatedMemory0(0);
|
||||
@ -525,6 +532,7 @@ public class ThreadImpl implements ThreadMXBean {
|
||||
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);
|
||||
|
@ -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
|
||||
@ -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
|
||||
@ -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)
|
||||
|
@ -105,6 +105,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 21
|
||||
*/
|
||||
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.
|
||||
|
@ -57,6 +57,11 @@ public class HotSpotThreadImpl extends ThreadImpl implements ThreadMXBean {
|
||||
return super.getThreadUserTime(ids);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getTotalThreadAllocatedBytes() {
|
||||
return super.getTotalThreadAllocatedBytes();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getCurrentThreadAllocatedBytes() {
|
||||
return super.getCurrentThreadAllocatedBytes();
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2011, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2011, 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
|
||||
@ -23,7 +23,7 @@
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 6173675 8231209
|
||||
* @bug 6173675 8231209 8304074
|
||||
* @summary Basic test of ThreadMXBean.getThreadAllocatedBytes
|
||||
* @author Paul Hohensee
|
||||
*/
|
||||
@ -33,6 +33,7 @@ import java.lang.management.*;
|
||||
public class ThreadAllocatedMemory {
|
||||
private static com.sun.management.ThreadMXBean mbean =
|
||||
(com.sun.management.ThreadMXBean)ManagementFactory.getThreadMXBean();
|
||||
private static boolean testFailed = false;
|
||||
private static volatile boolean done = false;
|
||||
private static volatile boolean done1 = false;
|
||||
private static Object obj = new Object();
|
||||
@ -55,6 +56,13 @@ public class ThreadAllocatedMemory {
|
||||
// Test many threads that are not this one
|
||||
testGetThreadsAllocatedBytes();
|
||||
|
||||
// Test cumulative Java thread allocation since JVM launch
|
||||
testGetTotalThreadAllocatedBytes();
|
||||
|
||||
if (testFailed) {
|
||||
throw new RuntimeException("TEST FAILED");
|
||||
}
|
||||
|
||||
System.out.println("Test passed");
|
||||
}
|
||||
|
||||
@ -92,13 +100,15 @@ public class ThreadAllocatedMemory {
|
||||
}
|
||||
|
||||
private static void testGetCurrentThreadAllocatedBytes() {
|
||||
Thread curThread = Thread.currentThread();
|
||||
|
||||
long size = mbean.getCurrentThreadAllocatedBytes();
|
||||
ensureValidSize(size);
|
||||
ensureValidSize(curThread, size);
|
||||
|
||||
// do some more allocation
|
||||
doit();
|
||||
|
||||
checkResult(Thread.currentThread(), size,
|
||||
checkResult(curThread, size,
|
||||
mbean.getCurrentThreadAllocatedBytes());
|
||||
}
|
||||
|
||||
@ -107,7 +117,7 @@ public class ThreadAllocatedMemory {
|
||||
long id = curThread.getId();
|
||||
|
||||
long size = mbean.getThreadAllocatedBytes(id);
|
||||
ensureValidSize(size);
|
||||
ensureValidSize(curThread, size);
|
||||
|
||||
// do some more allocation
|
||||
doit();
|
||||
@ -119,7 +129,8 @@ public class ThreadAllocatedMemory {
|
||||
throws Exception {
|
||||
|
||||
// start a thread
|
||||
done = false; done1 = false;
|
||||
done = false;
|
||||
done1 = false;
|
||||
Thread curThread = new MyThread("MyThread");
|
||||
curThread.start();
|
||||
long id = curThread.getId();
|
||||
@ -128,7 +139,7 @@ public class ThreadAllocatedMemory {
|
||||
waitUntilThreadBlocked(curThread);
|
||||
|
||||
long size = mbean.getThreadAllocatedBytes(id);
|
||||
ensureValidSize(size);
|
||||
ensureValidSize(curThread, size);
|
||||
|
||||
// let thread go to do some more allocation
|
||||
synchronized (obj) {
|
||||
@ -152,8 +163,7 @@ public class ThreadAllocatedMemory {
|
||||
try {
|
||||
curThread.join();
|
||||
} catch (InterruptedException e) {
|
||||
System.out.println("Unexpected exception is thrown.");
|
||||
e.printStackTrace(System.out);
|
||||
reportUnexpected(e, "during join");
|
||||
}
|
||||
}
|
||||
|
||||
@ -161,7 +171,8 @@ public class ThreadAllocatedMemory {
|
||||
throws Exception {
|
||||
|
||||
// start threads
|
||||
done = false; done1 = false;
|
||||
done = false;
|
||||
done1 = false;
|
||||
for (int i = 0; i < NUM_THREADS; i++) {
|
||||
threads[i] = new MyThread("MyThread-" + i);
|
||||
threads[i].start();
|
||||
@ -172,7 +183,7 @@ public class ThreadAllocatedMemory {
|
||||
|
||||
for (int i = 0; i < NUM_THREADS; i++) {
|
||||
sizes[i] = mbean.getThreadAllocatedBytes(threads[i].getId());
|
||||
ensureValidSize(sizes[i]);
|
||||
ensureValidSize(threads[i], sizes[i]);
|
||||
}
|
||||
|
||||
// let threads go to do some more allocation
|
||||
@ -201,38 +212,106 @@ public class ThreadAllocatedMemory {
|
||||
try {
|
||||
threads[i].join();
|
||||
} catch (InterruptedException e) {
|
||||
System.out.println("Unexpected exception is thrown.");
|
||||
e.printStackTrace(System.out);
|
||||
reportUnexpected(e, "during join");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void ensureValidSize(long size) {
|
||||
private static void testGetTotalThreadAllocatedBytes()
|
||||
throws Exception {
|
||||
|
||||
// baseline should be positive
|
||||
Thread curThread = Thread.currentThread();
|
||||
long cumulativeSize = mbean.getTotalThreadAllocatedBytes();
|
||||
if (cumulativeSize <= 0) {
|
||||
throw new RuntimeException(
|
||||
"Invalid allocated bytes returned for " + curThread.getName() + " = " + cumulativeSize);
|
||||
}
|
||||
|
||||
// start threads
|
||||
done = false;
|
||||
done1 = false;
|
||||
for (int i = 0; i < NUM_THREADS; i++) {
|
||||
threads[i] = new MyThread("MyThread-" + i);
|
||||
threads[i].start();
|
||||
}
|
||||
|
||||
// wait for threads to block after doing some allocation
|
||||
waitUntilThreadsBlocked();
|
||||
|
||||
// check after threads are blocked
|
||||
cumulativeSize = checkResult(curThread, cumulativeSize, mbean.getTotalThreadAllocatedBytes());
|
||||
|
||||
// let threads go to do some more allocation
|
||||
synchronized (obj) {
|
||||
done = true;
|
||||
obj.notifyAll();
|
||||
}
|
||||
|
||||
// wait for threads to get going again. we don't care if we
|
||||
// catch them in mid-execution or if some of them haven't
|
||||
// restarted after we're done sleeping.
|
||||
goSleep(400);
|
||||
|
||||
System.out.println("Done sleeping");
|
||||
|
||||
// check while threads are running
|
||||
cumulativeSize = checkResult(curThread, cumulativeSize, mbean.getTotalThreadAllocatedBytes());
|
||||
|
||||
// let threads exit
|
||||
synchronized (obj) {
|
||||
done1 = true;
|
||||
obj.notifyAll();
|
||||
}
|
||||
|
||||
for (int i = 0; i < NUM_THREADS; i++) {
|
||||
try {
|
||||
threads[i].join();
|
||||
} catch (InterruptedException e) {
|
||||
reportUnexpected(e, "during join");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// check after threads exit
|
||||
checkResult(curThread, cumulativeSize, mbean.getTotalThreadAllocatedBytes());
|
||||
}
|
||||
|
||||
private static void ensureValidSize(Thread curThread, long size) {
|
||||
// implementation could have started measurement when
|
||||
// measurement was enabled, in which case size can be 0
|
||||
if (size < 0) {
|
||||
throw new RuntimeException(
|
||||
"Invalid allocated bytes returned = " + size);
|
||||
"Invalid allocated bytes returned for thread " +
|
||||
curThread.getName() + " = " + size);
|
||||
}
|
||||
}
|
||||
|
||||
private static void checkResult(Thread curThread,
|
||||
long prev_size, long curr_size) {
|
||||
if (curr_size < prev_size) {
|
||||
throw new RuntimeException("Allocated bytes " + curr_size +
|
||||
" expected >= " + prev_size);
|
||||
}
|
||||
private static long checkResult(Thread curThread,
|
||||
long prevSize, long currSize) {
|
||||
System.out.println(curThread.getName() +
|
||||
" Previous allocated bytes = " + prev_size +
|
||||
" Current allocated bytes = " + curr_size);
|
||||
" Previous allocated bytes = " + prevSize +
|
||||
" Current allocated bytes = " + currSize);
|
||||
if (currSize < prevSize) {
|
||||
throw new RuntimeException("TEST FAILED: " +
|
||||
curThread.getName() +
|
||||
" previous allocated bytes = " + prevSize +
|
||||
" > current allocated bytes = " + currSize);
|
||||
}
|
||||
return currSize;
|
||||
}
|
||||
|
||||
private static void reportUnexpected(Exception e, String when) {
|
||||
System.out.println("Unexpected exception thrown " + when + ".");
|
||||
e.printStackTrace(System.out);
|
||||
testFailed = true;
|
||||
}
|
||||
|
||||
private static void goSleep(long ms) throws Exception {
|
||||
try {
|
||||
Thread.sleep(ms);
|
||||
} catch (InterruptedException e) {
|
||||
System.out.println("Unexpected exception is thrown.");
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
@ -287,34 +366,23 @@ public class ThreadAllocatedMemory {
|
||||
try {
|
||||
obj.wait();
|
||||
} catch (InterruptedException e) {
|
||||
System.out.println("Unexpected exception is thrown.");
|
||||
e.printStackTrace(System.out);
|
||||
reportUnexpected(e, "while !done");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
long size1 = mbean.getThreadAllocatedBytes(getId());
|
||||
long prevSize = mbean.getThreadAllocatedBytes(getId());
|
||||
ThreadAllocatedMemory.doit();
|
||||
long size2 = mbean.getThreadAllocatedBytes(getId());
|
||||
|
||||
System.out.println(getName() + ": " +
|
||||
"ThreadAllocatedBytes = " + size1 +
|
||||
" ThreadAllocatedBytes = " + size2);
|
||||
|
||||
if (size1 > size2) {
|
||||
throw new RuntimeException(getName() +
|
||||
" ThreadAllocatedBytes = " + size1 +
|
||||
" > ThreadAllocatedBytes = " + size2);
|
||||
}
|
||||
long currSize = mbean.getThreadAllocatedBytes(getId());
|
||||
checkResult(this, prevSize, currSize);
|
||||
|
||||
synchronized (obj) {
|
||||
while (!done1) {
|
||||
try {
|
||||
obj.wait();
|
||||
} catch (InterruptedException e) {
|
||||
System.out.println("Unexpected exception is thrown.");
|
||||
e.printStackTrace(System.out);
|
||||
reportUnexpected(e, "while !done1");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2011, 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
|
||||
@ -47,7 +47,6 @@ public class ThreadAllocatedMemoryArray {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// start threads, wait for them to block
|
||||
long[] ids = new long[NUM_THREADS];
|
||||
|
||||
@ -59,7 +58,6 @@ public class ThreadAllocatedMemoryArray {
|
||||
|
||||
waitUntilThreadBlocked();
|
||||
|
||||
|
||||
// disable allocated memory measurement
|
||||
if (mbean.isThreadAllocatedMemoryEnabled()) {
|
||||
mbean.setThreadAllocatedMemoryEnabled(false);
|
||||
@ -117,19 +115,9 @@ public class ThreadAllocatedMemoryArray {
|
||||
// restarted after we're done sleeping.
|
||||
goSleep(400);
|
||||
|
||||
long[] sizes1 = mbean.getThreadAllocatedBytes(ids);
|
||||
|
||||
long[] afterSizes = mbean.getThreadAllocatedBytes(ids);
|
||||
for (int i = 0; i < NUM_THREADS; i++) {
|
||||
long newSize = sizes1[i];
|
||||
if (sizes[i] > newSize) {
|
||||
throw new RuntimeException("TEST FAILED: " +
|
||||
threads[i].getName() +
|
||||
" previous allocated bytes = " + sizes[i] +
|
||||
" > current allocated bytes = " + newSize);
|
||||
}
|
||||
System.out.println(threads[i].getName() +
|
||||
" Previous allocated bytes = " + sizes[i] +
|
||||
" Current allocated bytes = " + newSize);
|
||||
checkResult(threads[i], sizes[i], afterSizes[i]);
|
||||
}
|
||||
|
||||
try {
|
||||
@ -147,7 +135,6 @@ public class ThreadAllocatedMemoryArray {
|
||||
"Caught expected IllegalArgumentException: " + e.getMessage());
|
||||
}
|
||||
|
||||
|
||||
// let threads exit
|
||||
synchronized (obj) {
|
||||
done1 = true;
|
||||
@ -158,9 +145,7 @@ public class ThreadAllocatedMemoryArray {
|
||||
try {
|
||||
threads[i].join();
|
||||
} catch (InterruptedException e) {
|
||||
System.out.println("Unexpected exception is thrown.");
|
||||
e.printStackTrace(System.out);
|
||||
testFailed = true;
|
||||
reportUnexpected(e, "during join");
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -173,11 +158,30 @@ public class ThreadAllocatedMemoryArray {
|
||||
}
|
||||
|
||||
|
||||
private static void checkResult(Thread curThread,
|
||||
long prevSize, long currSize) {
|
||||
System.out.println(curThread.getName() +
|
||||
" Previous allocated bytes = " + prevSize +
|
||||
" Current allocated bytes = " + currSize);
|
||||
if (currSize < prevSize) {
|
||||
throw new RuntimeException("TEST FAILED: " +
|
||||
curThread.getName() +
|
||||
" previous allocated bytes = " + prevSize +
|
||||
" > current allocated bytes = " + currSize);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private static void reportUnexpected(Exception e, String when) {
|
||||
System.out.println("Unexpected exception thrown " + when + ".");
|
||||
e.printStackTrace(System.out);
|
||||
testFailed = true;
|
||||
}
|
||||
|
||||
private static void goSleep(long ms) throws Exception {
|
||||
try {
|
||||
Thread.sleep(ms);
|
||||
} catch (InterruptedException e) {
|
||||
System.out.println("Unexpected exception is thrown.");
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
@ -221,9 +225,7 @@ public class ThreadAllocatedMemoryArray {
|
||||
try {
|
||||
obj.wait();
|
||||
} catch (InterruptedException e) {
|
||||
System.out.println("Unexpected exception is thrown.");
|
||||
e.printStackTrace(System.out);
|
||||
testFailed = true;
|
||||
reportUnexpected(e, "while !done");
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -236,9 +238,7 @@ public class ThreadAllocatedMemoryArray {
|
||||
try {
|
||||
obj.wait();
|
||||
} catch (InterruptedException e) {
|
||||
System.out.println("Unexpected exception is thrown.");
|
||||
e.printStackTrace(System.out);
|
||||
testFailed = true;
|
||||
reportUnexpected(e, "while !done");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user