@Exported(value=true)
See: Description
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 | 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 | Description |
---|---|
ResourceAccuracy |
ResourceAccuracy reflects the accuracy of an amount being requested though a
ResourceMeter.
|
Exception | Description |
---|---|
ResourceRequestDeniedException |
ResourceRequestDeniedException indicates a resource exception.
|
The architecture identifies three major components:
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 example FILE_OPEN opening a file
or SOCKET_WRITE writing to a socket
.
ResourceMeter
s track the usage of a ResourceType.
The ResourceMeters SimpleMeter
,
NotifyingMeter
,
BoundedMeter
, and ThrottledMeter
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.
ResourceRequest
to the matching ResourceType. The resources instrumented include:
System.err
, System.in
, System.out
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)
.
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.
AsynchronousFileChannel
, 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 |
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 |
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.
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 |
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.
DatagramChannel
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 |
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_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 |
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) |
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();
}
}
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
Copyright © 2014, 2015, Oracle and/or its affiliates. All rights reserved.