2012-07-23 40 views
3

我想研究Java程序的內存訪問模式。有沒有一個框架或我可以實現這一目標的方法。有沒有辦法找到Java程序訪問哪些內存地址以及按什麼順序訪問?

假設有一個程序P,它依次訪問內存地址m1,m2,m3等等。我希望能夠按照該順序查看這些訪問,並且如果可能,還可以訪問哪種類型的對象?

更新(添加對Durandal的建議):

我可以隨時通過PIN儀器運行Java程序查找內存訪問模式。除了這樣做,這一切都很好,我將失去內存地址映射到對象。我想要做的研究的一個重要方面是能夠將內存使用情況與相應類型(Class)進行映射。

儘管正確地提到內存使用模式將取決於JVM實現,但我想將其作爲研究的後續步驟。現在,我正在尋找字節碼工具。 (糾正我,如果我走錯了方向!)

我怎麼認爲字節碼檢測將幫助我分析緩存使用情況? 之前有任何解釋!這只是我想要做的一個方面。當內存訪問模式(如從PIN或修改的虛擬機或其他)獲得的信息不足以向我提供有關不同對象(或屬於特定類的對象)使用緩存的信息時, 。假設我得到字節碼訪問爲

ObjectA 
ObjectB 
ObjectC 
... 

很容易找到對象的大小。如果這是對象的第一次訪問,我還可以查找對象的內存訪問是否爲內存分配。然後,假設JVM在運行時會分配連續內存,我可以假設緩存的使用情況(通過運行緩存模擬)。現在,這不是一個很好的假設,但仍然給我緩存使用的上限(至少我相信如此)。

+2

你爲什麼要這樣做?你會如何使用這些信息?我問的原因是,似乎你應該以另一種方式去做。 – 2012-07-23 09:27:52

+0

如果我在某些基準測試中得到這個內存跟蹤,那麼我可以將它用於幾個目的,例如通過Java程序查找物理內存的生成使用模式,緩存使用情況等。然後我想探索改進的可能性,特別是併發程序的緩存。由於內存跟蹤很容易通過PIN儀器獲得,因此已經針對C/C++進行了此類研究。我想爲Java字節碼做類似的研究。 – Ankit 2012-07-23 16:11:23

+0

字節碼是針對虛擬機的。因此它沒有字節碼中的高速緩存或存儲位置。這用於生成本機代碼,但是這個本機代碼可以在應用程序的整個生命週期內被多次編譯。此外,對象可以在程序的整個生命週期中移動到多個位置,因此其地址不是很有意義。 – 2012-07-23 16:39:26

回答

2

那麼你總是可以做到這一點:改變虛擬機。有一些完全用Java編寫的JVM實現,可能會改變它來收集你想要的數據。但是,我堅信內存訪問模式取決於在運行程序的特定虛擬機上很多(因爲它們會在內存中以不同的方式組織數據)。不同的虛擬機=不同的訪問模式。如果您測量的虛擬機具有JIT,則它也將取決於JIT是否啓動。

真的收集所有內存訪問的方法是在某種沙箱環境下運行虛擬機並計算其訪問次數(可以在某些模擬器中或在MMU的幫助下完成)。編輯(問題更新 - 僅限字節碼工具):使用字節碼工具,您基本上非常接近工具分析器所做的工作。您現在的主要問題是您無法輕鬆建立對象與內存地址之間的關係。我可以想到兩種方法來規避這種情況:

  • 有一個(JRE私人,但可用)類sun.misc。不安全,可以得到你的對象,字段和數組的絕對內存地址(它有很多方法來做到這一點)。如果您測試字節碼以調用實用程序方法進行計數,則可以使用不安全來確定將要使用的地址。然而,不安全是特定於實現的,垃圾收集器可能會在堆周圍移動對象。這可能是也可能不是你想要衡量的。至少這可以通過合理的努力來實現。

  • 你可以拋棄的存儲器地址概念完全和(分別爲陣列身份和指數)與對象標識字段替換它。然後,分析工具將需要跟蹤對象和訪問的字段。你唯一需要注意的是你必須保持對象引用的方式不會阻塞垃圾回收器(例如使用WeakReferences)。這也不應太難實施。這種方法不會識別熱點內存的位置,而是熱點對象/域

這兩個問題都會對測量產生一些影響,因爲收集到的數據與被分析的代碼存儲在同一個堆中。如果這是非常不可取的,那麼可以使用JNI來收集堆外數據。

+0

感謝您指出JVM實現的東西。但是,我的目標有點不同(抱歉,起初在這個問題上不太清楚)。我已經更新了這個問題,以包含我的具體目標。 – Ankit 2012-07-23 16:22:10

+0

與字節代碼檢測一起,有一些可能性可能適合您的要求。我已經在最新的答案中概括了兩個。 – Durandal 2012-07-23 16:43:42

+0

我想我會放棄映射到物理內存的想法,並在保持領域的前提下前進。你能否指出一個合理的框架,我可以用來減少我的工作? – Ankit 2012-07-24 00:19:39

0

Java程序的哪個部分?由「public static void main(String [] args){...」)加載並且以前可訪問的類組成的Java「用戶空間」,或者包含後臺內存管理,垃圾收集,調試設施,管理設施等。

如果您正在尋找真正的內存地址,那麼您需要調試JVM。這與調試Java程序非常不同,因爲內存抽象層存在於真實內存和「用戶空間」程序之間。爲了調諧真實的內存訪問,你不能重寫Java程序,你需要重寫JVM。

字節碼插入仍然是「用戶空間」Java程序的一部分,這意味着您將永遠無法通過字節碼插入來確定絕對內存地址。實際上,JVM引用到真實存儲器地址的「用戶空間」映射對於同一個對象來說甚至不會隨着時間的推移而保持不變。

相關問題