|
JavaTM 2 Platform Standard Ed. 6 |
|||||||||
上一個類別 下一個類別 | 框架 無框架 | |||||||||
摘要: 巢狀 | 欄位 | 建構子 | 方法 | 詳細資訊: 欄位 | 建構子 | 方法 |
public interface Instrumentation
此類別提供檢測 Java 程式語言程式碼所需的服務。檢測是向方法中添加位元組碼,以搜集各種工具所使用的資料。由於更改完全是進行添加,所以這些工具不修改應用程序的狀態或行為。這種無害工具的例子包括鏡像代理、分析器、覆寫分析器和事件記錄器。
獲取 Instrumentation
介面的實例有兩種方式:
當 JVM 以指示一個代理類別的方式啟動時,將傳遞給代理類別的 premain
方法一個 Instrumentation
實例。
當 JVM 提供某種機制在 JVM 啟動之後某一時刻啟動代理時,將傳遞給代理程式碼的 agentmain
方法一個 Instrumentation
實例。
這些機制在套件規範中描述。
如果某個代理獲得了 Instrumentation
實例,它便可以在任何時候調用該實例上的方法。
方法摘要 | |
---|---|
void |
addTransformer(ClassFileTransformer transformer)
註冊提供的轉換器。 |
void |
addTransformer(ClassFileTransformer transformer,
boolean canRetransform)
註冊提供的轉換器。 |
void |
appendToBootstrapClassLoaderSearch(JarFile jarfile)
指定 JAR 檔案,檢測類別由引導類別載入器定義。 |
void |
appendToSystemClassLoaderSearch(JarFile jarfile)
指定 JAR 檔案,檢測類別由系統類別載入器定義。 |
Class[] |
getAllLoadedClasses()
返回 JVM 當前載入的全部類別的陣列。 |
Class[] |
getInitiatedClasses(ClassLoader loader)
返回所有初始化載入器是 loader 的類別的陣列。 |
long |
getObjectSize(Object objectToSize)
返回指定物件使用的特定於實作的近似存儲量。 |
boolean |
isModifiableClass(Class<?> theClass)
確定一個類別是否可以被 retransformation 或 redefinition 修改。 |
boolean |
isNativeMethodPrefixSupported()
返回當前 JVM 配置是否支持設置本機方法前綴。 |
boolean |
isRedefineClassesSupported()
返回當前 JVM 配置是否支持類別的重定義。 |
boolean |
isRetransformClassesSupported()
返回當前 JVM 配置是否支持類別的重轉換。 |
void |
redefineClasses(ClassDefinition... definitions)
使用提供的類別檔案重定義提供的類別集。 |
boolean |
removeTransformer(ClassFileTransformer transformer)
註銷提供的轉換器。 |
void |
retransformClasses(Class<?>... classes)
重轉換提供的類別集。 |
void |
setNativeMethodPrefix(ClassFileTransformer transformer,
String prefix)
通過允許重試,將前綴應用到名稱,此方法修改本機方法解析的失敗處理。 |
方法詳細資訊 |
---|
void addTransformer(ClassFileTransformer transformer, boolean canRetransform)
canRetransform
為 true,那麼重轉換類別時也將調用該轉換器。
有關轉換調用的順序,請參見 ClassFileTransformer.transform
。
如果轉換器在執行過程中拋出異常,JVM 將仍然按順序調用其他已註冊轉換器。可以多次添加相同的轉換器,但建議最好創建一個新的轉換器類別實例來避免這樣做。
此方法旨在用於檢測,正如類別規範所述。
transformer
- 要註冊的轉換器canRetransform
- 此轉換器的轉換是否可以重轉換
NullPointerException
- 如果傳遞了 null
轉換器
UnsupportedOperationException
- 如果 canRetransform
為 true 但當前 JVM 的配置不允許重轉換(isRetransformClassesSupported()
為 false)。void addTransformer(ClassFileTransformer transformer)
與 addTransformer(transformer, false)
相同。
transformer
- 要註冊的轉換器
NullPointerException
- 如果傳遞了一個 null
轉換器addTransformer(ClassFileTransformer,boolean)
boolean removeTransformer(ClassFileTransformer transformer)
transformer
- 要註銷的轉換器
NullPointerException
- 如果傳遞了一個 null
轉換器boolean isRetransformClassesSupported()
Can-Retransform-Classes
清單屬性在代理 JAR 檔案中設置為 true
(如套件規範所述),且 JVM 支持此性能時,才支持重轉換。
在單個 JVM 的單個實例化過程中,多次調用此方法將總是返回相同的答案。
retransformClasses(java.lang.Class>...)
void retransformClasses(Class<?>... classes) throws UnmodifiableClassException
此函數為檢測已載入類別提供了方便。
當最初載入了類別或重定義了類別時,初始類別檔案位元組可以使用 ClassFileTransformer
轉換。
此函數返回轉換進程(以前是否發生過轉換)。
此轉換按以下步驟進行:
canRetransform
設為 false 的轉換器,上一次類別載入或重定義期間 transform
返回的位元組將被重新用於轉換的輸出;注意,這等價於不做更改地重新應用前一個轉換;沒有調用 transform
的情況除外。
canRetransform
設為 true 的轉換器,在這些轉換器中調用 transform
方法
轉換的順序在 transform
方法中描述。在自動重新應用不可重轉換的轉換時,也將使用這一順序。
最初的類別檔案位元組表示(應用轉換前)傳遞給 ClassLoader.defineClass
或 redefineClasses
的位元組,但有可能不完全比對。常數池的佈局或內容可能不同。常數池的條目可能多一些或少一些。常數池條目的順序可能不同,但是,方法位元組碼中常數池的索引將是對應的。一些屬性可能不存在。在順序沒有意義的地方(例如,方法的順序),可能不保留順序。
此方法在一個集合上操作,以便允許同時對多個類別進行相互依賴的更改(重轉換類別 A 要求重轉換類別 B)。
如果重轉換的方法有活動的堆疊(stack)訊框,那麼這些活動的幀將繼續運行原方法的位元組碼。重轉換的方法將用於新的調用。
此方法不會引起任何初始化操作,JVM 慣例語義下發生的初始化除外。換句話說,重定義一個類別不會引起其初始化方法的運行。靜態變數的值將與調用之前的值一樣。
重轉換類別的實例不受影響。
重轉換可能會更改方法體、常數池和屬性。重轉換不得添加、移除、重命名欄位或方法;不得更改方法簽章、繼承關係。在以後的版本中,可能會取消這些限制。在應用轉換之前,類別檔案位元組不會被檢查、驗證和安裝。如果結果位元組錯誤,此方法將拋出異常。
如果此方法拋出異常,則不會重轉換任何類別。
此方法旨在用於檢測,正如類別規範所述。
classes
- 要轉換的類別陣列;
允許長度為 0 陣列,在這種情況下,此方法不執行任何操作
UnmodifiableClassException
- 如果不能修改指定的類別(isModifiableClass(java.lang.Class>)
返回 false
)
UnsupportedOperationException
- 如果 JVM 的當前配置不允許重轉換(isRetransformClassesSupported()
為 false),或者重轉換試圖做出不受支持的更改
ClassFormatError
- 如果資料不包含有效的類別
NoClassDefFoundError
- 如果類別檔案中的名稱不等於類別的名稱
UnsupportedClassVersionError
- 如果類別檔案版本號不受支持
ClassCircularityError
- 如果新類別包含循環
LinkageError
- 如果發生連接錯誤
NullPointerException
- 如果提供的類別陣列或其任意元件為 null
。isRetransformClassesSupported()
,
addTransformer(java.lang.instrument.ClassFileTransformer, boolean)
,
ClassFileTransformer
boolean isRedefineClassesSupported()
Can-Retransform-Classes
清單屬性在代理 JAR 檔案中設置為 true
(如套件規範所述),且 JVM 支持此性能時,才支持重轉換。
在執行單個 JVM 的單實例化過程中,對此方法的多次調用將始終返回同一應答。
redefineClasses(java.lang.instrument.ClassDefinition...)
void redefineClasses(ClassDefinition... definitions) throws ClassNotFoundException, UnmodifiableClassException
此方法用於替代類別的定義,而不參考現有的類別檔案位元組,這與 fix-and-continue 除錯過程中重新編譯源程式碼時所做的一樣。需要轉換現有類別檔案位元組的地方(例如,位元組碼檢測中)應該使用 retransformClasses
。
此方法在一個集合上操作,以便允許同時對多個類別進行相互依賴的更改(重定義類別 A 要求重定義類別 B)。
如果重定義的方法有活動的堆疊(stack)訊框,那麼這些活動的幀將繼續運行原方法的位元組碼。將在新的調用上使用此重定義的方法。
此方法不會引起任何初始化操作,JVM 慣例語義下發生的初始化除外。換句話說,重定義一個類別不會引起其初始化方法的運行。靜態變數的值將與調用之前的值一樣。
重定義類別的實例不受影響。
重定義可能會更改方法體、常數池和屬性。重定義不得添加、移除、重命名欄位或方法;不得更改方法簽章、繼承關係。在以後的版本中,可能會取消這些限制。在應用轉換之前,類別檔案位元組不會被檢查、驗證和安裝。如果結果位元組錯誤,此方法將拋出異常。
如果此方法拋出異常,則不會重定義任何類別。
此方法旨在用於檢測,正如類別規範所述。
definitions
- 要使用相應定義來進行重定義的類別陣列;允許長度為 0 陣列,在這種情況下,此方法不執行任何操作
UnmodifiableClassException
- 如果無法修改指定的類別(isModifiableClass(java.lang.Class>)
返回 false
)
UnsupportedOperationException
- 如果 JVM 的當前配置不允許重定義(isRedefineClassesSupported()
為 false)或重定義試圖做出不受支持的更改
ClassFormatError
- 如果資料不包含有效類別
NoClassDefFoundError
- 如果類別檔案中的名稱與類別名稱不相等
UnsupportedClassVersionError
- 如果類別檔案版本號不受支持
ClassCircularityError
- 如果新類別包含循環
LinkageError
- 如果發生連接錯誤
NullPointerException
- 如果提供的定義陣列或其任何元件為 null
。
ClassNotFoundException
- 不會拋出(存在只是為了相容)isRedefineClassesSupported()
,
addTransformer(java.lang.instrument.ClassFileTransformer, boolean)
,
ClassFileTransformer
boolean isModifiableClass(Class<?> theClass)
true
。
如果類別不能被修改,那麼此方法返回 false
。
對於要重轉換的類別,isRetransformClassesSupported()
也必須為 true。但 isRetransformClassesSupported()
的值不影響此函數返回的值。
對於要重定義的類別,isRedefineClassesSupported()
也必須為 true。但 isRedefineClassesSupported()
的值不影響此函數返回的值。
基本類別(例如 java.lang.Integer.TYPE
)和陣列類別不可修改。
NullPointerException
- 如果指定的類別為 null
。retransformClasses(java.lang.Class>...)
,
isRetransformClassesSupported()
,
redefineClasses(java.lang.instrument.ClassDefinition...)
,
isRedefineClassesSupported()
Class[] getAllLoadedClasses()
Class[] getInitiatedClasses(ClassLoader loader)
loader
的類別的陣列。如果提供的載入器為 null
,則返回由引導類別載入器初始化的類別。
loader
- 將返回其初始化類別列表的載入器
loader
的類別的陣列;如果沒有,則返回長度為 0 陣列long getObjectSize(Object objectToSize)
objectToSize
- 需要確定大小的物件
NullPointerException
- 如果提供的 Object 為 null
。void appendToBootstrapClassLoaderSearch(JarFile jarfile)
當虛擬機器的內置類別載入器(稱為「引導類別載入器」)未能成功搜尋到類別時,JAR 檔案
中的條目也將被搜尋。
可以多次使用此方法,按照調用此方法的順序添加多個要搜尋的 JAR 檔案。
除了需要引導類別載入器為檢測而定義的類別或資源外,代理應該注意確保 JAR 不包含任何其他類別或資源。
違反此規定將導致難以診斷的不可預料行為。例如,假設有載入器 L,L 的代理父載入器為引導類別載入器。
此外,有一個類別 C 的方法,有一個 L 定義的類別,參考了非公共存取類別 C$1。如果 JAR 檔案包含類別 C$1,那麼引導類別載入器的代理將導致 C$1 被引導類別載入器定義。此例中將拋出 IllegalAccessError
,這可能導致應用程序失敗。一個避免這類別問題的辦法是,對檢測類別使用唯一的套件名稱。
Java 虛擬機器規範規定,後續嘗試解析 Java 虛擬機器以前未能成功解析的符號參考將總是失敗,並拋出與最初解析嘗試失敗時相同的錯誤。因此,如果 JAR 檔案包含的某個條目對應於 Java 虛擬機器未能成功解析參考的類別,那麼後續嘗試解析該參考將總是失敗,並拋出與最初解析嘗試失敗時相同的錯誤。
jarfile
- 當引導類別載入器未成功搜尋到類別時要搜尋的 JAR 檔案。
NullPointerException
- 如果 jarfile
為 null
。appendToSystemClassLoaderSearch(java.util.jar.JarFile)
,
ClassLoader
,
JarFile
void appendToSystemClassLoaderSearch(JarFile jarfile)
getSystemClassLoader()
)未能成功搜尋到類別時,JarFile
中的條目也將被搜尋。
可以多次使用此方法,按照調用此方法的順序添加多個要搜尋的 JAR 檔案。
除了需要系統類別載入器為檢測而定義的類別或資源外,代理應該注意確保 JAR 不包含任何其他類別或資源。
違反此規定將導致難以診斷的不可預料行為。(參見 appendToBootstrapClassLoaderSearch
)。
如果實作了名為 appendToClassPathForInstrumentation
的方法(帶有一個型別為 java.lang.String
的參數),那麼系統類別載入器支持添加要搜尋的 JAR 檔案。不要求該方法具有 public
存取權。JAR 檔案名可以通過對 jarfile
調用 getName()
方法獲取,並將作為參數提供給 appendtoClassPathForInstrumentation
方法。
Java 虛擬機器規範規定,後續嘗試解析 Java 虛擬機器以前未能成功解析的符號參考將總是失敗,並拋出與最初解析嘗試失敗時相同的錯誤。因此,如果 JAR 檔案包含的某個條目對應於 Java 虛擬機器未能成功解析參考的類別,那麼後續嘗試解析該參考將總是失敗,並拋出與最初解析嘗試失敗時相同的錯誤。
此方法不更改 java.class.path
系統屬性
的值。
jarfile
- 當系統類別載入器未成功搜尋到類別時要搜尋的 JAR 檔案。
UnsupportedOperationException
- 如果系統類別載入器不支持添加要搜尋的 JAR 檔案。
NullPointerException
- 如果 jarfile
為 null
。appendToBootstrapClassLoaderSearch(java.util.jar.JarFile)
,
ClassLoader.getSystemClassLoader()
,
JarFile
boolean isNativeMethodPrefixSupported()
Can-Set-Native-Method-Prefix
清單屬性在代理 JAR 檔案中設置為 true
(如套件規範所述),且 JVM 支持此性能時,才支持設置本機方法前綴。
在單個 JVM 的單個實例化過程中,多次調用此方法將總是返回相同的應答。
setNativeMethodPrefix(java.lang.instrument.ClassFileTransformer, java.lang.String)
void setNativeMethodPrefix(ClassFileTransformer transformer, String prefix)
ClassFileTransformer
一起使用時,它允許檢測本機方法。
由於本機方法不能直接檢測(它們沒有位元組碼),因此必須使用可以檢測的非本機方法包裹它們。例如,如果有:
native boolean foo(int x);那麼可以轉換類別檔案(在類別的初始定義過程中使用 ClassFileTransformer),使之變成:
boolean foo(int x) { ... record entry to foo ... return wrapped_foo(x); } native boolean wrapped_foo(int x);其中
foo
變為實際本機方法的套件裝器,並帶有附加前綴 "wrapped_"。注意,將 "wrapped_" 作為前綴並不合適,因為它很有可能與現有方法重名,因此 "$$$MyAgentWrapped$$$_" 之類別更加合適,但那將減少這些範例的可讀性。
外覆器將允許在本機方法調用上收集資料,但現在的問題在於如何連接包裹的方法與本機實作。
也就是說,方法 wrapped_foo
需要被解析為 foo
的本機實作,即:
Java_somePackage_someClass_foo(JNIEnv* env, jint x)此函數允許指定前綴並進行恰當的解析。 明確地說,當標準解析失敗時,解析將重新嘗試考慮前綴。進行解析有兩種方式,使用 JNI 函數
RegisterNatives
的顯式解析和常規自動解析。對於 RegisterNatives
,JVM 將嘗試以下關聯:
method(foo) -> nativeImplementation(foo)若此操作失敗,解析將重試,將指定的前綴添加到方法名,產生校正解析:
method(wrapped_foo) -> nativeImplementation(foo)對於自動解析,JVM 將嘗試:
method(wrapped_foo) -> nativeImplementation(wrapped_foo)若此操作失敗,解析將重試,從實作名刪除指定的前綴,產生校正解析:
method(wrapped_foo) -> nativeImplementation(foo)注意,前綴只在標準解析失敗時使用,因此可以有選擇地包裹本機方法。 每個
ClassFileTransformer
可以執行其本身的位元組程式碼轉換,因此可能要應用多個外覆器層。所以每個轉換器需要其自己的前綴。轉換是按順序應用的,因此前綴(如果應用)也將按相同的順序應用(參見 addTransformer
)。
所以,如果三個轉換器應用了外覆器,foo
將變為 $trans3_$trans2_$trans1_foo
。但是,如果第二個轉換器沒有對 foo
應用外覆器,那麼它將是 $trans3_$trans1_foo
。要有效的確定前綴序列,僅當其非本機外覆器存在時才應用中間前綴。因此,在最後一個範例中,即使 $trans1_foo
不是本機方法,$trans1_
前綴也將應用,因為 $trans1_foo
存在。
transformer
- 使用此前綴包裹的 ClassFileTransformer。prefix
- 已應用到包裹的本機方法的前綴。
NullPointerException
- 如果傳入 null
轉換器。
UnsupportedOperationException
- 如果 JVM 的當前配置不允許設置本機方法前綴(isNativeMethodPrefixSupported()
為 false)。
IllegalArgumentException
- 如果轉換器沒有註冊(參見 addTransformer
)。
|
JavaTM 2 Platform Standard Ed. 6 |
|||||||||
上一個類別 下一個類別 | 框架 無框架 | |||||||||
摘要: 巢狀 | 欄位 | 建構子 | 方法 | 詳細資訊: 欄位 | 建構子 | 方法 |
版權所有 2008 Sun Microsystems, Inc. 保留所有權利。請遵守GNU General Public License, version 2 only。