モジュール jdk.management.resource

パッケージ jdk.management.resource

非推奨。
リソース管理は、置き換えのない削除のために推奨されていません。
リソース追跡コンテキスト、メーターおよびファクトリ。 リソース追跡パッケージは、リソース使用を追跡するための基本フレームワークと実装を提供します。

このアーキテクチャは3つの主要コンポーネントを識別します。

  • リソース追跡API - 各ResourceContextに対して、リソース・メーターとバインド・スレッドのコンテキストを提供します。
  • リソース計装 - 特定のJava Runtimeサブシステムのフックを実装して、情報を収集し、リソース承認をリクエストし、リソース・アクセスを許可、制限、または拒否するメカニズムを適用します。 各リソースの計測では、呼出し元スレッドに関連付けられているResourceContextを動的に探して、ResourceRequestを対応するResourceTypeに転送します。 ネイティブ・ライブラリやファイル記述子やソケットなどの仮想マシンで使用されるリソースは、計測も追跡もされません。 計測対象のリソースは次のとおりです。
    • FileDescriptor - オープン・ファイル記述子の数、合計
      • 明示的ファイルに関連付けられたFileDescriptor
      • ソケットおよびソケット・チャネルに関連付けられたFileDescriptor
    • ファイル - オープン・ファイルの数、送信バイト数、受信バイト数、合計
      • FileInputStream、FileOutputStream、RandomAccessFile
      • 同期および非同期のNIO FileChannel
      • 標準ストリーム(System.errSystem.inSystem.out)
    • ソケットおよびダイアグラム - オープン・ソケットの数、送信バイト数、受信バイト数、送信ダイアグラム、受信ダイアグラム、合計
      • Socket、ServerSocket、DatagramSocket
      • NIO SocketChannelおよびDatagramChannel
      • NIO AsynchronousSocketChannel
    • ヒープ - 割当て済バイト数、保持されたバイト数、合計割当て
    • スレッド - アクティブなスレッド数、リソース・コンテキスト当たりのCPU時間
  • リソース・マネージャ - リソース使用量の監視とリソース・ポリシーの実装を行う信頼できる外部エンティティ。 リソース・マネージャは、アプリケーション・ドメインのリソース・コンシューマ・スレッドをResourceContextとバインドします。 リソース・マネージャおよびリソース管理ポリシーは含まれていません。

リソース管理はセキュリティで保護されたAPIであり、APIへのアクセスはSecurityManager (ある場合)およびRuntimePermission("jdk.management.resource.getResourceContextFactory")によって許可されます。

コマンド行オプション-XX:+ResourceManagement-XX:ResourceManagementSampleInterval=nn (milliseconds)および-XX:+UseG1GCを使用してリソース追跡を適宜有効化すると、保持されたヒープ量が確保されます。

リソースのアカウンティングとスレッド化

ライブラリ・ベースのリソースの場合、ファイルのオープン、ストリームの読取りなどでリソースを消費しているスレッドを使って使用状況を測定し、ResourceMeterに記録します。 計測は、アクティビティを記録する共通のパブリックAPIに割り込むことによって実施されます。

アプリケーション・スレッドの使用は保護されています。 リソース・マネージャがアプリケーションと競合しないようにし、また、リソース管理計測への再帰コールを引き起こす可能性がある関数を呼び出さないようにする必要があります。 ResourceRequestインタフェースとResourceApproverインタフェースの実装は、簡潔、軽量および自己完結型であることが必要です。 これらのインタフェースを介した呼出しは非常に頻繁に発生するため、計測対象のすべてのリソースのパフォーマンスに影響を及ぼす可能性があります。 たとえば、デバッグ出力を挿入するためにSystem.out.printlnを呼び出すと、再帰コールが発生します。 これにより、予期しないループが発生したり、クラスの初期化が不完全になる可能性があります。 たとえば、StackOverflowErrorExceptionInInitializerErrorなどの現象があります。

リソース割当ての場合、リソース・マネージャ・ポリシーでリソースの使用を遅くしたり拒否したりできるように、通常、メーターの更新はアクションが実行される前に行われます。 リソースの解放はリソースが解放された後に発生するので、リソース数が処理途中で減分されることはありません。 割当て済で未使用のリソースは、その残りの部分が解放されます。 たとえば、ファイルを開いたときにSecurityExceptionが発生すると、オープン・ファイル数のカウントが減り、ファイルの読取り時にファイルから読み取られたデータ量がリクエストされた量よりも少ない場合は、読み取られなかったバイト数分のカウントが減ります。

ファイル・リソースの追跡

ファイルのオープン、読取りおよび書込みに使用されるリソースについては、AsynchronousFileChannelFileChannelFileInputStreamFileOutputStreamおよびRandomAccessFileの各クラスが追跡されます。 報告されたResourceIdは、APIに指定されたパス名です(ただし、AsynchronousFileChannelの場合は除き、そこではFileDescriptor番号またはハンドルがResourceIdになります)。 アプリケーションのスレッドを使用して次のメソッドを計測し、指定のResourceMeterにリソース使用量を累計します。 リソースの使用を拒否するには、ResourceApproverまたはResourceMeterでゼロ(0)を返すかResourceRequestDeniedExceptionをスローします。 拒否されると、I/O操作がIOExceptionで失敗します。

ファイルを開くと、それが閉じるまでResourceContextが記憶されます。 チャネルまたはファイルを閉じると、開いたときと同じResourceContextのカウントが減ります。

ファイル・リソースの追跡
ResourceType 増分 減分
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メソッド、
System.in.read
リクエストされた読取りバイト数から実際の読取りバイト数を差し引いた数 length
FILE_WRITE AsynchronousFileChannel.write
FileChannel.write
FileOutputStream.write
RandomAccessFile.writeメソッド、
System.err出力および書込みメソッド、
System.out出力および書込みメソッド
例外 length

ファイル記述子の追跡

ファイル記述子がチャネル、ファイルおよびソケットを開く場合に使用するリソースが追跡されます。 ファイル記述子が決まる前にリソース・チェックが行われる可能性があるため、ファイル記述子を割り当てるためのリソース・リクエストには、必ずしもファイル記述子のResourceIdを指定する必要はありません。 ただし、使用可能な場合には、ファイル記述子番号またはハンドラがResourceIdの名前として使用されます。 アプリケーションのスレッドを使用して次のメソッドを計測し、指定のResourceMeterにリソース使用量を累計します。 リソースの使用を拒否するには、ResourceApproverまたはResourceMeterでゼロ(0)を返すかResourceRequestDeniedExceptionをスローします。 拒否されると、I/O操作がIOExceptionで失敗します。

ファイル記述子が割り当てられると、それが閉じるまでResourceContextが記憶されます。 ファイル記述子を閉じると、開いたときと同じResourceContextのカウントが減ります。

ファイル記述子リソースの追跡
ResourceType 増分 減分
FILEDESCRIPTOR_OPEN AsynchronousFileChannel.open
AsynchronousServerSocketChannel.accept
AsynchronousServerSocketChannel.open
AsynchronousSocketChannel.open
DatagramChannel.open
DatagramSocket
FileChannel.open
FileInputStream
FileOutputStream
RandomAccessFile
ServerSocketChannel.accept
ServerSocketChannel.open
ServerSocket (バインドしている場合)、
ServerSocket.accept
ServerSocket.bind (バインドしていない場合)、
Socket (接続している場合)、
Socket.connect (接続していない場合)
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およびSocketの場合は、それぞれソケットのバインド時または接続時です。 バインドや接続が行われるのは、ソケットのインスタンス化中またはインスタンス化後です。

ソケット・リソースの追跡

ソケット経由でデータを開いたり送受信する場合に使用されるリソースについては、ソケットとソケット・チャネル、ダイアグラム・ソケットとダイアグラム・チャネル、および非同期ソケット・チャネルが追跡されます。 これにはSSLサーバーとクライアントのソケットを含みます。 報告されるResourceIdは、ローカル・ネットワーク・ポートのアドレスです。 アプリケーションのスレッドを使用して次のメソッドを計測し、指定のResourceMeterにリソース使用量を累計します。 リソースの使用を拒否するには、ResourceApproverまたはResourceMeterでゼロ(0)を返すかResourceRequestDeniedExceptionをスローします。 拒否されると、I/O操作がIOExceptionで失敗します。

ソケットを開くと、それが閉じるまでResourceContextが記憶されます。 チャネル・ソケットを閉じると、開いたときと同じResourceContextのカウントが減ります。

ソケット・リソース使用量の追跡
ResourceType 増分 減分
SOCKET_OPEN AsynchronousServerSocketChannel.accept
AsynchronousServerSocketChannel.bind (バインドされていない場合)、
AsynchronousSocketChannel.bind (バインドされていない場合)、
AsynchronousSocketChannel.connect (バインドされていない場合)、
ServerSocketChannel.bind (バインドされていない場合)、
ServerSocket.accept
ServerSocket.bind (バインドされていない場合)、
Socket.bind (バインドされていない場合)、
Socket.connect (バインドされていない場合)、
SocketChannel.bind (バインドされていない場合)、
SocketChannel.connect (バインドされていない場合)
AsynchronousServerSocketChannel.close
AsynchronousSocketChannel.close
ServerSocketChannel.close
ServerSocket.close
Socket.close
SocketChannel.close
1
SOCKET_READ AsynchronousSocketChannel.read
Socket.getInputStream().read
SocketChannel.read
リクエストされた読取りバイト数から実際の読取りバイト数を差し引いた数 length
SOCKET_WRITE AsynchronousSocketChannel.write
Socket.getOutputStream().write
SocketChannel.write
例外 length
前述の内容について、SOCKET_OPENリソース数が増分されるタイミングは、オブジェクトの作成時ではなく、オブジェクトのバインド時です。 バインドが行われるのは、ソケットがまだバインドされていない場合に接続したときです。

データグラム・リソースの追跡

データグラムを開いたり送受信する場合に使用されるリソースについては、DatagramChannelおよびDatagramSocketの各クラスが追跡されます。 報告されるResourceIdは、ローカル・ネットワーク・ポートのアドレスです。 アプリケーションのスレッドを使用して次のメソッドを計測し、指定のResourceMeterにリソース使用量を累計します。 リソースの使用を拒否するには、ResourceApproverまたはResourceMeterでゼロ(0)を返すかResourceRequestDeniedExceptionをスローします。 拒否されると、I/O操作がIOExceptionで失敗します。

DatagramSocketを開くと、それが閉じるまでResourceContextが記憶されます。 チャネルまたはソケットを閉じると、開いたときと同じResourceContextのカウントが減ります。

データグラム・リソース使用量の追跡
ResourceType 増分 減分
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
例外 1
DATAGRAM_SENT DatagramChannel.send
DatagramChannel.write
DatagramSocket.send
例外 1
DATAGRAM_READ DatagramChannel.read
DatagramChannel.receive
DatagramSocket.receive
リクエストされた読取りバイト数から実際の読取りバイト数を差し引いた数 +ダイアグラムの長さ
DATAGRAM_WRITE DatagramChannel.send
DatagramChannel.write
DatagramSocket.send
例外 +ダイアグラムの長さ
前述の内容について、DATAGRAM_OPENリソース数が増分されるタイミングは、オブジェクトの作成時ではなく、オブジェクトのバインド時です。 バインドが行われるのは、ソケットがまだバインドされていない場合に接続したとき(DatagramChannelの場合は送信したとき)です。

スレッド・リソースの追跡

スレッド・リソースを追跡するには、スレッドを監視して、スレッドにバインドされているResourceContext内のResourceMeterに報告します。 スレッドが作成されて終了すると、THREAD_CREATEDメーターが更新されます。 例外がスローされると、スレッドの作成は実行されません。 メーターから返された量がゼロ(0)の場合、ResourceRequestDeniedExceptionがスローされます。

スレッドがResourceContextからアンバインドされると、スレッドがコンテキストにバインドされてからのCPU時間の累積使用量が、スレッドにバインドされているResourceContext内のTHREAD_CPU ResourceMeterに適用されます。 更新はアンバインドされるスレッドを使用して実行されます。

システム・スレッド以外のスレッドは、最初はunassignedContextに対してバインドされます。 新しいスレッドは、新しいThreadを起動するスレッドのResourceContextに暗黙的にバインドされます。 ThreadのRunnableは、必要に応じて目的のコンテキストに明示的にバインドする必要があります。

定期的な更新は監視スレッドで実行します。監視スレッドは、各ResourceContext内でアクティブなスレッドをサンプリングし、各スレッドのCPU時間の更新を実行します。 ResourceApproverまたはResourceMeterのアクションでは、ゼロ(0)を返したり、ResourceRequestDeniedExceptionをスローすることがありますが、それがリソースを使用しているアプリケーションに影響するかどうかは、プラットフォームによって異なります。 更新のタイミングはサンプリングによって異なる場合があります。 THREAD_CPUメーターの粒度を設定した場合の正常な動作では、粒度境界を越えたときに通知が発生します。 サンプリング間隔は、コマンド・ライン・スイッチ-XX:ResourceManagementSampleInterval=nnを使用した実装で設定されます。 デフォルトのサンプリング間隔は100ミリ秒(0.1秒)ごとです。 サンプリングを無効化するには、引数0 (ゼロ)を指定します。 引数がゼロ(0)よりも小さい場合は、デフォルトが使用されます。

THREAD_CREATEDおよびTHREAD_CPUに報告されるResourceIdは、Long.toString(threadID)という形式のthreadIDです。

スレッドが作成されると、終了するまでResourceContextが記憶されます。 スレッドが終了すると、開いたときと同じResourceContextの作成済スレッドのカウントが減ります。

CPUリソースの追跡
ResourceType 増分 減分
THREAD_CPU 実行中のスレッド なし ナノ秒
THREAD_CREATED スレッドの構築 スレッドの終了 カウント

ヒープ・リソースの追跡

ヒープ・リソースを追跡するには、スレッドとガベージ・コレクタのアクティビティを監視して、スレッドにバインドされているResourceContext内のResourceMeterに使用状況を報告します。

スレッドがResourceContextからアンバインドされると、スレッドがコンテキストにバインドされてからのヒープ割当ての累積使用量が、スレッドにバインドされているResourceContext内のHEAP_ALLOCATED ResourceMeterに適用されます。 更新はアンバインドされるスレッドを使用して実行されます。 HEAP_ALLOCATED値のサンプリング間隔はTHREAD_CPUメーターと同じです。 ResourceIdHEAP_ALLOCATEDthreadIdであり、スレッドごとに個別に報告されます。

HEAP_RETAINEDの使用量については、ガベージ・コレクタのアクティビティの結果として更新が発生します。 GCフェーズが終了すると、HEAP_RETAINEDの各メーターが更新されます。 保持されたヒープ量の精度は、ResourceId.getAccuracyメソッドからResourceAccuracy値として提供されます。 ResourceApproverまたはResourceMeterのアクションでは、ゼロ(0)を返したり、ResourceRequestDeniedExceptionをスローすることがありますが、それがリソースを使用しているアプリケーションに影響するかどうかは、プラットフォームによって異なります。 ResourceAccuracy.HIGHまたはResourceAccuracy.HIGHESTが指定されたHEAP_RETAINEDの更新は常に、メーターに設定された粒度に関係なく実施されます。 更新のタイミングはサンプリングやGC動作によって異なる場合があります。 HEAP_RETAINEDResourceId"Heap"です。

ヒープ・リソースの追跡
ResourceType 増分 減分
HEAP_ALLOCATED オブジェクト割当て なし 割当てバイト数(上限)
HEAP_RETAINED GCフェーズの終了時 GCフェーズの終了時 保持されたバイト数(上限)

FileOutputStreamによって書き込まれたバイト数をSimpleMeterを使用してカウントする例


    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();
        }
    }
 

NotifyingMeterとコールバックを使用してバイト数をカウントする例


    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());
    }
 
出力の生成

 cpu:         76960825 ns
 file open:          8 bytes
 file read:      82639 bytes
 file write:     82639 bytes
 heap total:    801624 bytes
 progress:       99188 bytes
 
 
実装要件:
特に指定しない限り、nullを引数としてコンストラクタまたはメソッドに渡すと、NullPointerExceptionがスローされます。
導入されたバージョン:
8u40
商用機能
これは、使用する前にロックを解除する必要のある商用機能です。 商用機能の詳細とロック解除方法については、http://www.oracle.com/technetwork/java/javaseproducts/をご覧ください。