Package jdk.management.resource
The architecture identifies three major components:
- Resource Tracking API - provides a context for resource meters
and binding threads to each
ResourceContext
.ResourceContextFactory
provides access to ResourceContexts and provides the main entry point to the API.ResourceContext
contains a set of ResourceMeters that track usage of resources by threads bound to the ResourceContext.ResourceType
s are used to identify a type of resource. For exampleFILE_OPEN opening a file
orSOCKET_WRITE writing to a socket
.ResourceMeter
s track the usage of a ResourceType. The ResourceMetersSimpleMeter
,NotifyingMeter
,BoundedMeter
, andThrottledMeter
count the resource use and approve, throttle, or deny resource use.ResourceId
s identify specific resources and the accuracy of the measurements.ResourceApprover
is an interface implemented by the resource manager and is notified of resource use. The response from the resource manager determines whether the resource is approved, limited or denied.
- Resource instrumentation - implements the hooks in specific Java Runtime
subsystems to gather information, request resource approvals and apply the
mechanisms to allow, limit, or deny resource access.
The instrumentation of each resource dynamically locates the ResourceContext
associated with the calling thread and forwards the
ResourceRequest
to the matching ResourceType. Resources used by native libraries or the virtual machine such as file descriptors or sockets are neither instrumented nor tracked. The resources instrumented include:- FileDescriptors - open file descriptor count, totals
- FileDescriptors associated with explicit files
- FileDescriptors associated with sockets and socket channels
- Files - open file count, bytes sent, bytes received, totals
- FileInputStream, FileOutputStream, RandomAccessFile
- NIO synchronous and asynchronous FileChannels
- Standard streams
System.err
,System.in
,System.out
- Sockets and datagrams - open socket count, bytes sent, bytes received,
datagrams sent, datagrams received, totals
- Socket, ServerSocket, DatagramSocket
- NIO SocketChannel and DatagramChannel
- NIO AsynchronousSocketChannel
- Heap - allocated and retained bytes, total allocations
- Threads - active thread count, CPU time per resource context
- FileDescriptors - open file descriptor count, totals
- Resource Manager - the trusted external entity that monitors resource usage
and implements a resource policy.
The resource manager binds resource consumer threads in the application
domain with a
ResourceContext
. A resource manager and resource management policy are not included.
Resource management is a security sensitive API and access to the API is allowed
by a SecurityManager, if any, and the
RuntimePermission("jdk.management.resource.getResourceContextFactory")
.
Resource tracking is enabled via the command line options
-XX:+ResourceManagement
and
-XX:ResourceManagementSampleInterval=nn (milliseconds)
and
-XX:+UseG1GC
as appropriate to provide retained heap amounts.
Resource Accounting and Threading
For library based resources, the thread that is consuming the resource, opening files, reading streams, etc. is used to measure and record the use in ResourceMeters. The instrumentation is accomplished by interposing on the common public APIs to record the activity.
The use of the application thread is sensitive. The resource manager
must not interfere with the application and must avoid calling functions
that might cause recursive calls to the resource management instrumentation.
Implementations of the ResourceRequest and
ResourceApprover interfaces
must be kept short, lightweight and be self contained. Calls
through these interfaces occur very frequently and can impact performance
of all instrumented resources.
For example, calling System.out.println
to
insert debugging output results in a recursive call. It can
cause unintentional loops and/or be a victim of incomplete class initialization.
Symptoms may include StackOverflowError or
ExceptionInInitializerError.
For resource allocation, the updates to the meters usually occur before the action is performed to allow the resource manager policy to slow or deny use of the resource. The release of resources happens after the resources are released so the resource counts are not prematurely decremented. For resources that have been allocated but not used, the remainder is released. For example, if a SecurityException occurs on opening a file, the count of open file count is reduced, or if when reading a file, if the amount of data read from the file is less than requested, the bytes not read reduce the count.
File Resource Tracking
Resources used to open, read and write files are tracked for the classesAsynchronousFileChannel
, FileChannel
,
FileInputStream
, FileOutputStream
,
and RandomAccessFile
. The ResourceId
reported is the pathname provided to the API except for AsynchronousFileChannel
where it is the FileDescriptor
number or handle. The methods below are
instrumented to accumulate the resource usage to the indicated
ResourceMeters using the thread of the
application. The resource consumption can be denied by the ResourceApprover
or ResourceMeter by returning zero or
throwing a ResourceRequestDeniedException.
When denied, the I/O operation fails with an IOException.
When a file is opened the ResourceContext is remembered until it is closed.
The close of the channel or file reduces the count in the same ResourceContext
that opened it.
ResourceType |
Incremented | Decremented | Amount |
---|---|---|---|
FILE_OPEN |
AsynchronousFileChannel.open , FileChannel.open , FileInputStream , FileOutputStream , RandomAccessFile |
AsynchronousFileChannel.close , FileChannel.close , FileInputStream.close , FileOutputStream.close , RandomAccessFile.close |
1 |
FILE_READ |
AsynchronousFileChannel.read , FileChannel.read , FileInputStream.read , RandomAccessFile.read methods, System.in.read |
requested number of bytes to read less number actually read | length |
FILE_WRITE |
AsynchronousFileChannel.write , FileChannel.write , FileOutputStream.write , RandomAccessFile.write methods,System.err print and write methods,System.out print and write methods |
Exception | length |
File Descriptor Tracking
Resources used by file descriptors to open channels, files, and sockets are tracked. Resource requests to allocate file descriptors do not necessarily provide the ResourceId of the file descriptor because the resource check may occur before the file descriptor is determined. If available however, the file descriptor number or handler is used as the name of the ResourceId. The methods below are instrumented to accumulate the resource usage to the indicated ResourceMeters using the thread of the application. The resource consumption can be denied by the ResourceApprover or ResourceMeter by returning zero or throwing a ResourceRequestDeniedException. When denied, the I/O operation fails with an IOException.
When a file descriptor is allocated the ResourceContext is remembered until it is closed.
The close of the file descriptor reduces the count in the same ResourceContext
that opened it.
ResourceType |
Incremented | Decremented | Amount |
---|---|---|---|
FILEDESCRIPTOR_OPEN |
AsynchronousFileChannel.open , AsynchronousServerSocketChannel.accept , AsynchronousServerSocketChannel.open , AsynchronousSocketChannel.open , DatagramChannel.open , DatagramSocket , FileChannel.open , FileInputStream , FileOutputStream , RandomAccessFile , ServerSocketChannel.accept , ServerSocketChannel.open , ServerSocket (if binding), ServerSocket.accept , ServerSocket.bind (if not bound), Socket (if connecting), Socket.connect (if not connected) SocketChannel.open |
AsynchronousFileChannel.close , AsynchronousServerSocketChannel.close , AsynchronousSocketChannel.close , DatagramChannel.close , DatagramSocket.close , FileChannel.close , FileInputStream.close , FileOutputStream.close ,RandomAccessFile.close ,ServerSocketChannel.close ,ServerSocket.close ,Socket.close ,SocketChannel.close |
1 |
In the foregoing, note that the resource count is updated when the corresponding native analog of the file descriptor is either allocated or closed. For
ServerSocket
s and Socket
s this occurs when the socket is
bound or connected, respectively. Binding or connecting may occur either
during instantiation of the socket or subsequent thereto.
Socket Resource Tracking
Resources used to open, send and receive data over sockets are tracked for sockets and socket channels, datagram sockets and datagram channels, and asynchronous socket channels. Note that this includes SSL server and client sockets. The ResourceId reported is the address of the local network port. The methods below are instrumented to accumulate the resource usage to the indicated ResourceMeters using the thread of the application. The resource consumption can be denied by the ResourceApprover or ResourceMeter by returning zero or throwing a ResourceRequestDeniedException. When denied, the I/O operation fails with an IOException.
When a socket is opened the ResourceContext is remembered until it is closed.
The close of the channel socket reduces the count in the same ResourceContext
that opened it.
ResourceType |
Incremented | Decremented | Amount |
---|---|---|---|
SOCKET_OPEN |
AsynchronousServerSocketChannel.accept , AsynchronousServerSocketChannel.bind (if not bound), AsynchronousSocketChannel.bind (if not bound), AsynchronousSocketChannel.connect (if not bound), ServerSocketChannel.bind (if not bound), ServerSocket.accept , ServerSocket.bind (if not bound), Socket.bind (if not bound), Socket.connect (if not bound), SocketChannel.bind (if not bound), SocketChannel.connect (if not bound) |
AsynchronousServerSocketChannel.close , AsynchronousSocketChannel.close , ServerSocketChannel.close , ServerSocket.close , Socket.close , SocketChannel.close |
1 |
SOCKET_READ |
AsynchronousSocketChannel.read , Socket.getInputStream().read ,SocketChannel.read |
requested number of bytes to read less number actually read | length |
SOCKET_WRITE |
AsynchronousSocketChannel.write , Socket.getOutputStream().write , SocketChannel.write |
Exception | length |
In the foregoing, note that incrementing the
SOCKET_OPEN
resource count
occurs when the object is bound, not when it is created. Binding may occur
while connecting if the socket was not previously bound.
Datagram Resource Tracking
Resources used to open, send and receive datagrams are tracked for theDatagramChannel
and DatagramSocket
classes.
The ResourceId reported is the address of the local network port.
The methods below are instrumented to accumulate the resource usage to
the indicated ResourceMeters using the thread of the application.
The resource consumption can be denied by the ResourceApprover or
ResourceMeter by returning zero or
throwing a ResourceRequestDeniedException.
When denied, the I/O operation fails with an IOException.
When a DatagramSocket is opened the ResourceContext is remembered until it is closed.
The close of the channel or socket reduces the count in the same ResourceContext
that opened it.
ResourceType |
Incremented | Decremented | Amount |
---|---|---|---|
DATAGRAM_OPEN |
DatagramChannel.bind , DatagramChannel.connect , DatagramChannel.send , DatagramSocket.bind , DatagramSocket.connect , |
DatagramChannel.close , DatagramSocket.close |
1 |
DATAGRAM_RECEIVED |
DatagramChannel.read , DatagramChannel.receive , DatagramSocket.receive |
Exception | 1 |
DATAGRAM_SENT |
DatagramChannel.send , DatagramChannel.write , DatagramSocket.send |
Exception | 1 |
DATAGRAM_READ |
DatagramChannel.read , DatagramChannel.receive , DatagramSocket.receive |
requested number of bytes to read less number actually read | +datagram length |
DATAGRAM_WRITE |
DatagramChannel.send , DatagramChannel.write , DatagramSocket.send |
Exception | +datagram length |
In the foregoing, note that incrementing the
DATAGRAM_OPEN
resource count
occurs when the object is bound, not when it is created. Binding may occur
while connecting or, in the case of DatagramChannel
, while sending,
if the socket was not previously bound.
Thread Resource Tracking
Thread resources are tracked by monitoring threads and reporting to the ResourceMeters in the ResourceContext bound to the threads. When threads are created and exit,THREAD_CREATED
meters are updated.
Thread creation is prevented if an exception is thrown.
If the amount returned from the meter is zero, a
ResourceRequestDeniedException is thrown.
When a thread is unbound from a ResourceContext, the accumulated CPU time
usage since the thread was bound to the context is applied to the
THREAD_CPU
ResourceMeter in the
ResourceContext
bound to the thread.
The update is performed using the thread being unbound.
Threads that are not system threads are initially bound to the
unassignedContext
.
New threads are implicitly bound to the ResourceContext
of the thread invoking new Thread
.
The Thread's Runnable
should explicitly
bind
to the desired context as required.
Periodic updates are performed by a monitoring thread
that samples the threads active in each ResourceContext and performs
an update for the CPU time of each thread.
The ResourceApprover or
ResourceMeter actions may return zero
or throw ResourceRequestDeniedException but it is platform specific whether it
has any effect on the application consuming the resource.
The timing of updates may vary due to sampling.
The normal behavior of setting granularity of a THREAD_CPU
meter
applies, notifications occur when crossing granularity boundaries.
The sample interval is set by the implementation
using the command line switch -XX:ResourceManagementSampleInterval=nn
.
The default is to sample every 100 milliseconds (.1 second).
The sampling can be disabled by providing an argument of 0 (zero)
.
If the argument is less than zero, the default is used.
The ResourceId reported for
THREAD_CREATED
and
THREAD_CPU
is
the threadID
formatted as in Long.toString(threadID)
.
When a thread is created the ResourceContext
is remembered until it exits.
The exit of the thread reduces the count of created threads in the same ResourceContext
that opened it.
ResourceType |
Incremented | Decremented | Amount |
---|---|---|---|
THREAD_CPU |
Threads running | never | nanoseconds |
THREAD_CREATED |
Thread construction | Thread exit | count |
Heap Resource Tracking
Heap Resources are tracked by monitoring threads and garbage collector activity and reporting usage to the ResourceMeters in the ResourceContext bound to the threads.
When a thread is unbound from a ResourceContext, the accumulated heap
allocation usage since the thread was bound to the context is applied to the
HEAP_ALLOCATED
ResourceMeter
in the
ResourceContext bound to the thread.
The update is performed using the thread being unbound.
The HEAP_ALLOCATED
value sample interval is the same as the
THREAD_CPU
meter.
The ResourceId is the threadId
for
HEAP_ALLOCATED
and is reported
for each thread individually.
For HEAP_RETAINED
usage, updates occur as the result of garbage collector
activity. When a GC phase completes, the meters for HEAP_RETAINED
are updated.
The accuracy of the retained heap amounts are available from the
ResourceId.getAccuracy
method as a
ResourceAccuracy
value.
The ResourceApprover or
ResourceMeter actions may return zero
or throw ResourceRequestDeniedException but it is platform specific whether it
has any effect on the application consuming the resource.
HEAP_RETAINED updates with
ResourceAccuracy.HIGH or
ResourceAccuracy.HIGHEST are always delivered without regard
to the granularity set on the meter.
The timing of updates may vary due to sampling and GC behavior.
The ResourceId for HEAP_RETAINED
is "Heap"
.
ResourceType |
Incremented | Decremented | Amount |
---|---|---|---|
HEAP_ALLOCATED |
Object allocation | never | bytes allocated (upper bound) |
HEAP_RETAINED |
On GC phase completion | On GC phase completion | bytes retained (upper bound) |
Example using a SimpleMeter to count the bytes written with FileOutputStream
void test1() {
ResourceContextFactory rfactory = ResourceContextFactory.getInstance();
ResourceContext rc1 = rfactory.create("context1");
ResourceMeter writeMeter = SimpleMeter.create(ResourceType.FILE_WRITE);
rc1.addResourceMeter(writeMeter);
rc1.bindThreadContext();
try {
long bytesWritten = writeFile("example1.tmp");
assert bytesWritten == writeMeter.get() : "Expected: " + bytesWritten + ", actual: " + writeMeter.get();
} finally {
ResourceContext.unbindThreadContext();
}
}
Example using a NotifyingMeter with callback to count bytes
public void test1() {
ResourceContextFactory rfactory = ResourceContextFactory.getInstance();
ResourceContext rcontext = rfactory.create("test");
SimpleMeter fileOpenMeter = SimpleMeter.create(ResourceType.FILE_OPEN);
rcontext.addResourceMeter(fileOpenMeter);
SimpleMeter fileWriteMeter = SimpleMeter.create(ResourceType.FILE_WRITE);
rcontext.addResourceMeter(fileWriteMeter);
SimpleMeter threadCPUMeter = SimpleMeter.create(ResourceType.THREAD_CPU);
rcontext.addResourceMeter(threadCPUMeter);
SimpleMeter heapAllocMeter = SimpleMeter.create(ResourceType.HEAP_ALLOCATED);
rcontext.addResourceMeter(heapAllocMeter);
AtomicLong progress = new AtomicLong();
NotifyingMeter fileReadMeter = NotifyingMeter.create(ResourceType.FILE_READ,
(ResourceMeter c, long prev, long amt, ResourceId id) -> {
// total up the lengths of the positive requests
progress.getAndAdd(Math.max(0, amt));
return amt;
});
rcontext.addResourceMeter(fileReadMeter);
rcontext.bindThreadContext();
try {
FileConsumer fc = FileConsumer.create();
fc.write();
fc.read();
} catch (IOException ioe) {
System.out.printf("ioe: %s%n", ioe);
} finally {
ResourceContext.unbindThreadContext();
}
System.out.printf(" cpu: %9d ns%n", threadCPUMeter.getValue());
System.out.printf(" file open: %9d bytes%n", fileOpenMeter.getValue());
System.out.printf(" file read: %9d bytes%n", fileReadMeter.getValue());
System.out.printf(" file write: %9d bytes%n", fileWriteMeter.getValue());
System.out.printf(" heap total: %9d bytes%n", heapAllocMeter.getValue());
System.out.printf(" progress: %9d bytes%n", progress.get());
}
Produces the output
cpu: 76960825 ns
file open: 8 bytes
file read: 82639 bytes
file write: 82639 bytes
heap total: 801624 bytes
progress: 99188 bytes
- Implementation Requirements:
- Unless otherwise specified, passing
null
as an argument to a constructor or method will cause aNullPointerException
to be thrown. - Since:
- 8u40
- Commercial feature
- This is a commercial feature that must be unlocked before being used. To learn more about commercial features and how to unlock them visit http://www.oracle.com/technetwork/java/javaseproducts/.
-
Interface Summary Interface Description ResourceApprover A ResourceApprover is a callback to approve resource requests.ResourceContext A set of ResourceMeters that accumulate resource usage by threads.ResourceId ResourceId provides a name and accuracy for a resource instance.ResourceMeter A resource meter with a current value and a ResourceType.ResourceRequest A ResourceRequest is an interface to allocate or release resources. -
Class Summary Class Description BoundedMeter A BoundedMeter enforces an upper bound, provides an approver callback for changes and allocates from an optional parent.NotifyingMeter A NotifyingMeter provides an approver callback for changes and allocates from an optional parent.ResourceContextFactory The ResourceContextFactory provides access to ResourceContext functions.ResourceType A ResourceType with a name.SimpleMeter A SimpleMeter counts resource requests and releases and allocates from an optional parent.ThrottledMeter A ThrottledMeter with bandwidth limit, an approver callback for requests and allocates from an optional parent. -
Enum Summary Enum Description ResourceAccuracy ResourceAccuracy reflects the accuracy of an amount being requested though a ResourceMeter. -
Exception Summary Exception Description ResourceRequestDeniedException ResourceRequestDeniedException indicates a resource exception.