JavaTM 2 Platform
Standard Ed. 6

java.lang.management
介面 MemoryPoolMXBean


public interface MemoryPoolMXBean

記憶體池的管理介面。記憶體池表示由 Java 虛擬機器管理的記憶體資源,由一個或多個記憶體管理器對記憶體池進行管理。

Java 虛擬機器具有此介面的實作類別的一個或多個實例。實作此介面的實例是 MXBean,可以通過調用 ManagementFactory.getMemoryPoolMXBeans() 方法或從平臺 MBeanServer 方法獲得。

MBeanServer 中惟一標識記憶體池的 MXBean 的 ObjectName 為:

java.lang:type=MemoryPool,name=pool's name

記憶體型別

Java 虛擬機器具有一個用於物件分派的堆積(heap)空間,還包含用於方法區域和 Java 虛擬機器執行的非堆積(heap)空間記憶體。Java 虛擬機器可以有一個或多個記憶體池。每個記憶體池表示一個記憶體區域,此記憶體區域可為以下型別之一:

記憶體使用量監視

記憶體池具有以下屬性:

1. 記憶體使用量

getUsage() 方法提供了記憶體池當前使用量的估計數。對於垃圾回收記憶體池,已使用的記憶體包括由池中所有物件(包括可到達 物件和不可達到 物件)佔用的記憶體。

通常,此方法是一個輕量操作,用於獲取近似記憶體使用量。對於某些記憶體池(例如,當物件未連續打包時),此方法可能成為開銷巨大的操作,要求進行計算以確定當前的記憶體使用量。如果是這樣,實作應該加以註釋。

2. 峰值記憶體使用量

Java 虛擬機器會維護自虛擬機器啟動或者峰值重置以來的記憶體池峰值記憶體使用量。峰值記憶體使用量由 getPeakUsage() 方法返回,通過調用 resetPeakUsage() 方法可將其重置。

3. 使用量閾值

每個記憶體池都有一個可管理的屬性,稱為使用量閾值,其預設值由 Java 虛擬機器提供。此預設值與平臺有關。可以通過 setUsageThreshold 方法設置使用量閾值。如果閾值設置為正數,將啟用此記憶體池中的使用量閾值超過檢查。如果使用率閾值設置為零,將禁用此記憶體池的使用量閾值超過檢查。isUsageThresholdSupported() 方法可用於確定是否支持此功能。

Java 虛擬機器在其最恰當的時候(通常在垃圾回收時)會對記憶體池逐個進行使用量閾值超過檢查。每個記憶體池均維護一個使用量閾值計數,每次 Java 虛擬機器檢測到記憶體池使用量超過閾值,此值都會加 1。

此可管理的使用量閾值屬性設計用於以低開銷監視記憶體使用量增加的趨勢。使用量閾值可能不適合某些記憶體池。例如,生存期垃圾回收器是在很多 Java 虛擬機器實作中都使用的一種常見的垃圾回收演算法,它按照生存時間管理劃分為兩代或多代的物件。很多對象都分派在最新的一代(稱為新生記憶體池)。新生記憶體池的設計使其很容易被填滿,回收新生記憶體池將會釋放其大部分記憶體空間,因為這種記憶體池包含了大多數生存時間短的物件,以及大多數在垃圾回收時不可到達的物件。在這種情況下,新生記憶體池不支持使用量閾值會更為合適。此外,如果在一個記憶體池中進行物件分派的開銷很小(例如,只是原子指針交換),Java 虛擬機器將可能不支持該記憶體池的使用量閾值,因為使用量閾值的開銷比物件分派的開銷大。

系統的記憶體使用量可以通過輪詢閾值通知機制進行監視。

  1. 輪詢

    通過調用所有記憶體池的 getUsage() 方法或調用支持使用量閾值的記憶體池的 isUsageThresholdExceeded() 方法,應用程序可以持續監視其記憶體使用量。以下的範例程式碼具有一個專門用於任務分派和處理的執行緒。每隔一段時間,它將根據其記憶體使用量確定是否應當接受和處理新任務。如果記憶體使用量超過了其使用量閾值,它會將所有未處理的任務重新分派給其他 VM 並停止接受新任務,直到記憶體使用量低於其使用量閾值。

      
           // Assume the usage threshold is supported for this pool.
           // Set the threshold to myThreshold above which no new tasks
           // should be taken.
           pool.setUsageThreshold(myThreshold);
           ....
    
           boolean lowMemory = false;
           while (true) {
              if (pool.isUsageThresholdExceeded()) {
                  // potential low memory, so redistribute tasks to other VMs
                  lowMemory = true;
                  redistributeTasks();
                  // stop receiving new tasks
                  stopReceivingTasks();
              } else {
                  if (lowMemory) {
                      // resume receiving tasks
                      lowMemory = false;
                      resumeReceivingTasks();
                  } 
                  // processing outstanding task
                  ...
              }
              // sleep for sometime
              try {
                  Thread.sleep(sometime);
              } catch (InterruptedException e) {
                  ...
              }
           }
           

    以上範例並沒有對以下兩種情況加以區分,即記憶體使用量臨時低於使用量閾值的情況和記憶體使用量在兩次迭代之間保持高於閾值的情況。由 getUsageThresholdCount() 方法返回的使用量閾值計數可用於確定在兩次輪詢之間返回的記憶體使用量是否低於閾值。

    以下是另一個範例,該範例在記憶體池出現記憶體空間不足時將採取一些操作,並會忽略在操作處理期間的記憶體使用量變化。

           // Assume the usage threshold is supported for this pool.
           // Set the threshold to myThreshold which determines if 
           // the application will take some action under low memory condition.
           pool.setUsageThreshold(myThreshold);
    
           int prevCrossingCount = 0;
           while (true) {
               // A busy loop to detect when the memory usage  
               // has exceeded the threshold.
               while (!pool.isUsageThresholdExceeded() || 
                      pool.getUsageThresholdCount() == prevCrossingCount) {
                   try {
                       Thread.sleep(sometime)
                   } catch (InterruptException e) {
                       ....
                   }
               }
    
               // Do some processing such as check for memory usage
               // and issue a warning
               ....
    
               // Gets the current threshold count. The busy loop will then
               // ignore any crossing of threshold happens during the processing.
               prevCrossingCount = pool.getUsageThresholdCount();
           }
           

  2. 使用量閾值通知

    使用量閾值通知將由 MemoryMXBean 發出。當 Java 虛擬機器檢測到記憶體池的記憶體使用量達到或超過其記憶體使用量閾值時,虛擬機器將觸發 MemoryMXBean ,發出使用量閾值超過通知。直到使用量降低到閾值以下,然後再次超過了閾值,才會再次產生使用量閾值超過通知。

    以下範例程式碼實作了與以上範例相同的邏輯,但使用了使用量閾值通知機制(而非輪詢)來檢測低記憶體情況。在此範例程式碼中,接收到通知時,通知偵聽器將通知另一個執行緒執行實際的操作,如重新分派未處理的任務、停止接受任務,或恢復接受任務等。handleNotification 方法應該設計為完成很少的工作,且無延遲地返回,以避免導致交付後續通知時出現延遲。耗時的操作應該使用獨立的執行緒來執行。通知偵聽器可以由多個執行緒共時調用,因此偵聽器執行的任務應該進行適當地同步。

      
           class MyListener implements javax.management.NotificationListener {
                public void handleNotification(Notification notification, Object handback)  {
                    String notifType = notification.getType();
                    if (notifType.equals(MemoryNotificationInfo.MEMORY_THRESHOLD_EXCEEDED)) {
                        // potential low memory, notify another thread
                        // to redistribute outstanding tasks to other VMs
                        // and stop receiving new tasks.
                        lowMemory = true;
                        notifyAnotherThread(lowMemory);
                    }
                }
           }
    
           // Register MyListener with MemoryMXBean  
           MemoryMXBean mbean = ManagementFactory.getMemoryMXBean();
           NotificationEmitter emitter = (NotificationEmitter) mbean;
           MyListener listener = new MyListener();
           emitter.addNotificationListener(listener, null, null);
    
           // Assume this pool supports a usage threshold.
           // Set the threshold to myThreshold above which no new tasks
           // should be taken.
           pool.setUsageThreshold(myThreshold);
           
           // Usage threshold detection is enabled and notification will be 
           // handled by MyListener.  Continue for other processing.
           ....
    
           

    無法保證 MemoryMXBean 何時發出閾值通知和交付通知。當調用通知偵聽器時,記憶體池的記憶體使用量可能已經多次超過使用量閾值。MemoryNotificationInfo.getCount() 方法將返回建構通知時記憶體使用量已超過使用量閾值的次數。可以將此值與 getUsageThresholdCount() 返回的當前使用量閾值計數進行比較,以確定是否出現了此類別情況。

4. 回收使用量閾值

回收使用量閾值是一個可管理屬性,僅適用於某些垃圾回收記憶體池。Java 虛擬機器通過在垃圾回收時回收記憶體池中未使用的物件,完成了記憶體空間的回收工作之後,記憶體池中某些經過垃圾回收的位元組仍在使用。回收使用量閾值允許為此位元組數設置一個值,這樣在超過該閾值的情況下,將由 MemoryMXBean 發出回收使用量超過通知。此外,回收使用量閾值計數將增加 1。

isCollectionUsageThresholdSupported() 方法可用於確定是否支持此功能。

Java 虛擬機器按記憶體池執行回收使用量閾值檢查。如果回收使用量閾值設置為正數,則將啟用此檢查。如果回收使用量閾值設置為零,將在此記憶體池上禁用此檢查。預設值為零。Java 虛擬機器將在垃圾回收時執行回收使用量閾值檢查。

某些垃圾回收記憶體池可能選擇不支持回收使用量閾值。例如,僅由持續共時垃圾回收器管理的記憶體池。在此記憶體池中,某個執行緒可以分派物件,而同時不使用的物件將由共時垃圾回收器進行回收。除非有定義良好的垃圾回收時間,該時間是檢查記憶體使用量的最恰當時間,否則就不應該支持回收使用量閾值。

回收使用量閾值設計用於監視 Java 虛擬機器進行記憶體空間回收工作之後的記憶體使用量。還可以採用與上述監視使用量閾值類似的方法,通過輪詢和閾值通知機制監視回收使用量閾值。

從以下版本開始:
1.5
另請參見:
JMX Specification., 存取 MXBeans 的方式

方法摘要
 MemoryUsage getCollectionUsage()
          返回 Java 虛擬機器最近回收了此記憶體池中的不使用的物件之後的記憶體使用量。
 long getCollectionUsageThreshold()
          返回此記憶體池的回收使用量閾值(以位元組為單位)。
 long getCollectionUsageThresholdCount()
          返回 Java 虛擬機器已檢測到記憶體使用量達到或超過回收使用量閾值的次數。
 String[] getMemoryManagerNames()
          返回管理此記憶體池的記憶體管理器的名稱。
 String getName()
          返回表示此記憶體池的名稱。
 MemoryUsage getPeakUsage()
          返回自 Java 虛擬機器啟動以來或自峰值重置以來此記憶體池的峰值記憶體使用量。
 MemoryType getType()
          返回此記憶體池的型別。
 MemoryUsage getUsage()
          返回此記憶體池的記憶體使用量的估計數。
 long getUsageThreshold()
          返回此記憶體池的使用量閾值(以位元組為單位)。
 long getUsageThresholdCount()
          返回記憶體使用量超過其閾值的次數。
 boolean isCollectionUsageThresholdExceeded()
          測試在 Java 虛擬機器最近一次回收工作之後,此記憶體池的記憶體使用量是否達到或超過了其回收使用量閾值。
 boolean isCollectionUsageThresholdSupported()
          測試此記憶體池是否支持回收使用量閾值。
 boolean isUsageThresholdExceeded()
          測試此記憶體池的使用量是否達到或超過其使用量閾值。
 boolean isUsageThresholdSupported()
          測試此記憶體池是否支持使用量閾值。
 boolean isValid()
          測試此記憶體池在 Java 虛擬機器中是否有效。
 void resetPeakUsage()
          將此記憶體池的峰值記憶體使用量統計重置為當前記憶體使用量。
 void setCollectionUsageThreshold(long threhsold)
          將此記憶體池的回收使用量閾值設置為給定的 threshold 值。
 void setUsageThreshold(long threshold)
          如果此記憶體池支持使用量閾值,則將此記憶體池的閾值設置為給定的 threshold 值。
 

方法詳細資訊

getName

String getName()
返回表示此記憶體池的名稱。

返回:
此記憶體池的名稱。

getType

MemoryType getType()
返回此記憶體池的型別。

MBeanServer 存取
MemoryType 的映射型別為 String,值為 MemoryType 的名稱。

返回:
此記憶體池的型別。

getUsage

MemoryUsage getUsage()
返回此記憶體池的記憶體使用量的估計數。如果此記憶體池無效(即不再存在),此方法將返回 null

此方法請求 Java 虛擬機器對此記憶體池的當前記憶體使用量進行最佳估算。對於某些記憶體池,此方法可能是開銷很大的操作,需要進行計算以確定估計數。如果是這種情況,實作應該加以註釋。

此方法設計用於監視系統記憶體使用量和檢測低記憶體情況。

MBeanServer 存取
MemoryUsage 的映射型別為 CompositeData,具有 MemoryUsage 中指定的那些屬性。

返回:
MemoryUsage 物件;或者,如果此記憶體池無效,則返回 null

getPeakUsage

MemoryUsage getPeakUsage()
返回自 Java 虛擬機器啟動以來或自峰值重置以來此記憶體池的峰值記憶體使用量。如果此記憶體池無效(即不再存在),此方法將返回 null

MBeanServer 存取
MemoryUsage 的映射型別為 CompositeData,具有 MemoryUsage 中指定的那些屬性。

返回:
表示峰值記憶體使用量的 MemoryUsage 物件;或者,如果此記憶體池無效,則返回 null

resetPeakUsage

void resetPeakUsage()
將此記憶體池的峰值記憶體使用量統計重置為當前記憶體使用量。

拋出:
SecurityException - 如果存在安全管理器,且調用方不具有 ManagementPermission("control")。

isValid

boolean isValid()
測試此記憶體池在 Java 虛擬機器中是否有效。一旦 Java 虛擬機器將記憶體池從記憶體系統刪除,該記憶體池就變為無效。

返回:
如果記憶體池在正在運行的 Java 虛擬機器中有效,則返回 true;否則返回 false

getMemoryManagerNames

String[] getMemoryManagerNames()
返回管理此記憶體池的記憶體管理器的名稱。每個記憶體池將由至少一個記憶體管理器進行管理。

返回:
String 物件的一個陣列,其中每個物件都是管理此記憶體池的記憶體管理器的名稱。

getUsageThreshold

long getUsageThreshold()
返回此記憶體池的使用量閾值(以位元組為單位)。每個記憶體池都具有一個與平臺有關的預設閾值。可以通過 setUsageThreshold 方法更改當前的使用量閾值。

返回:
此記憶體池的使用量閾值(以位元組為單位)。
拋出:
UnsupportedOperationException - 如果此記憶體池不支持使用量閾值。
另請參見:
isUsageThresholdSupported()

setUsageThreshold

void setUsageThreshold(long threshold)
如果此記憶體池支持使用量閾值,則將此記憶體池的閾值設置為給定的 threshold 值。如果閾值設置為正數,將啟用此記憶體池中的使用量閾值超過檢查。如果設置為零,則將禁用使用量閾值超過檢查。

參數:
threshold - 新閾值(以位元組為單位)。必須為非負數。
拋出:
IllegalArgumentException - 如果 threshold 為負或大於此記憶體池的最大記憶體量(如果已定義)。
UnsupportedOperationException - 如果此記憶體池不支持使用量閾值。
SecurityException - 如果存在安全管理器,且調用方不具有 ManagementPermission("control")。
另請參見:
isUsageThresholdSupported(), 使用量閾值

isUsageThresholdExceeded

boolean isUsageThresholdExceeded()
測試此記憶體池的使用量是否達到或超過其使用量閾值。

返回:
如果此記憶體池的使用量達到或超過了閾值,則返回 true;否則返回 false
拋出:
UnsupportedOperationException - 如果此記憶體池不支持使用量閾值。

getUsageThresholdCount

long getUsageThresholdCount()
返回記憶體使用量超過其閾值的次數。

返回:
記憶體使用量超過其閾值的次數。
拋出:
UnsupportedOperationException - 如果此記憶體池不支持使用量閾值。

isUsageThresholdSupported

boolean isUsageThresholdSupported()
測試此記憶體池是否支持使用量閾值。

返回:
如果此記憶體池支持使用量閾值,則返回 true;否則返回 false

getCollectionUsageThreshold

long getCollectionUsageThreshold()
返回此記憶體池的回收使用量閾值(以位元組為單位)。預設值為零。可以通過 setCollectionUsageThreshold 方法更改回收使用量閾值。

返回:
此記憶體池的回收使用量閾值(以位元組為單位)。
拋出:
UnsupportedOperationException - 如果此記憶體池不支持回收使用量閾值。
另請參見:
isCollectionUsageThresholdSupported()

setCollectionUsageThreshold

void setCollectionUsageThreshold(long threhsold)
將此記憶體池的回收使用量閾值設置為給定的 threshold 值。當此閾值設置為正數時,Java 虛擬機器將在對此記憶體池中不使用的物件進行了回收工作後,在最恰當的時間檢查記憶體使用量。

如果閾值設置為正數,將啟用此記憶體池中的回收使用量閾值超過檢查。如果設置為零,則將禁用回收使用量閾值超過檢查。

參數:
threhsold - 新的回收使用量閾值(以位元組為單位)。必須為非負數。
拋出:
IllegalArgumentException - 如果 threshold 為負或大於此記憶體池的最大記憶體量(如果已定義)。
UnsupportedOperationException - 如果此記憶體池不支持回收使用量閾值。
SecurityException - 如果存在安全管理器,且調用方不具有 ManagementPermission("control")。
另請參見:
isCollectionUsageThresholdSupported(), 回收使用量閾值

isCollectionUsageThresholdExceeded

boolean isCollectionUsageThresholdExceeded()
測試在 Java 虛擬機器最近一次回收工作之後,此記憶體池的記憶體使用量是否達到或超過了其回收使用量閾值。此方法不會請求 Java 虛擬機器執行其正常自動記憶體管理之外的任何垃圾回收操作。

返回:
如果在最近的回收操作中,此記憶體池的使用量達到或超過了回收使用閾值,則返回 true;否則返回 false
拋出:
UnsupportedOperationException - 如果此記憶體池不支持使用量閾值。

getCollectionUsageThresholdCount

long getCollectionUsageThresholdCount()
返回 Java 虛擬機器已檢測到記憶體使用量達到或超過回收使用量閾值的次數。

返回:
記憶體使用量達到或超過回收使用量閾值的次數。
拋出:
UnsupportedOperationException - 如果此記憶體池不支持回收使用量閾值。
另請參見:
isCollectionUsageThresholdSupported()

getCollectionUsage

MemoryUsage getCollectionUsage()
返回 Java 虛擬機器最近回收了此記憶體池中的不使用的物件之後的記憶體使用量。此方法不會請求 Java 虛擬機器執行其正常的自動記憶體管理之外的任何垃圾回收操作。如果 Java 虛擬機器不支持此方法,此方法將返回 null

MBeanServer 存取
MemoryUsage 的映射型別為 CompositeData,具有 MemoryUsage 中指定的那些屬性。

返回:
表示 Java 虛擬機器最近對不使用的物件進行了回收之後此記憶體池的記憶體使用量的 MemoryUsage;如果不支持此方法,則返回 null

isCollectionUsageThresholdSupported

boolean isCollectionUsageThresholdSupported()
測試此記憶體池是否支持回收使用量閾值。

返回:
如果此記憶體池支持回收使用量閾值,則返回 true;否則返回 false

JavaTM 2 Platform
Standard Ed. 6

提交錯誤或意見

版權所有 2008 Sun Microsystems, Inc. 保留所有權利。請遵守GNU General Public License, version 2 only