回答
將分配了new
的對象放置在堆上,但JIT/JVM 可能會優化它們以使用轉義分析進行堆棧。瞭解更多關於它in this article published on IBM developerWorks:
虛擬機可以使用一個名爲逃逸分析技術,通過它們可以告訴大家,某些對象仍然侷限於單一線程的整個生命週期,而且壽命是由一個壽命爲界給定的堆棧幀。這些對象可以安全地分配到堆棧而不是堆上。
你不可能直接控制堆棧分配,就像你無法預測GC何時運行一樣。如果你真的需要對存儲機制進行如此深入的控制,唯一的方法就是使用C/C++。
無論如何,在過分複雜你的軟件之前請三思。我上面鏈接的論文的結論對內存管理非常明確:
JVM出奇地擅長弄清楚我們以前只假定開發人員可以知道的事情。通過讓JVM根據具體情況在堆棧分配和堆分配之間進行選擇,我們可以獲得堆棧分配的性能優勢,而不會讓程序員因爲是在堆棧上還是在堆上分配而苦惱。
這並不意味着您永遠不需要對內存進行細粒度的控制,但是在大多數情況下,JVM可以優於一般程序員。
啊,非常好,謝謝!我想知道是否存在監測這種情況的工具。不過,我很懷疑。 – cabbagebot 2013-05-12 09:47:13
@cabbagebot我從來沒有嘗試過,但[VisualVM](http://visualvm.java.net/)可以幫助你。 – 2013-05-12 09:51:07
JLS說new
分配一個新的對象。 JLS 12.5:
「當評估類實例創建表達式(第15.9節)導致類實例化時,會顯式創建新的類實例。
JLS並未說明對象的分配位置。如果編譯器可以推斷(通過轉義分析)可達性規則允許在堆棧上分配一個對象,那麼這是允許的。
通常將JLS讀爲允許優化,其效果無法通過觀察執行程序的結果來檢測。顯然,最新版本的Java 7,執行的優化之一涉及優化異常創建/拋出/ catch代碼並用無條件跳轉語句(或類似的...)替換它。在某些情況下,這種優化涉及優化掉一個明確的new
陳述。
總之,new
表達通常導致堆分配,但有時對象在棧上分配,並且有時分配被完全優化掉。
- 1. Filter()關鍵字必須是字符串
- 2. 分配時是否必須使用initWithString?
- 3. 分配給X的表達必須是
- 4. 我是否必須刪除我用新分配的wchar_t?
- 5. WriteStream是否必須關閉?
- 6. 我們是否必須在打字稿中使用「this」關鍵字?
- 7. django - __init __()關鍵字必須是字符串
- 8. Redshift:是否使用必要的外鍵來利用分配鍵?
- 9. 參數是否必須匹配案例
- 10. 我是否必須配置SQLiteCommand對象?
- 11. PHP是否必須配合SQL?
- 12. 是否必須關閉()每個EntityManager?
- 13. 接收「的表達被分配必須是常量」當它是
- 14. 無法分配 - 必須是「UserProfile」實例
- 15. 我是否必須關閉瀏覽器才能刷新我的Java小程序?
- 16. Java新關鍵字
- 17. 鍵必須是字符串或符號
- 18. 我是否必須重新開始?
- 19. 如果使用連接表,關係是否必須是HABTM?
- 20. Java堆分配
- 21. 關鍵部分示例 - 是否有效?
- 22. 的Java n必須是正
- 23. Solr:如何顯示搜索的關鍵字是否匹配?
- 24. 是否必須始終更新一對多關係包實例?
- 25. 分配給'....'的表達式必須是常量
- 26. 維度表是否必須具有主鍵?
- 27. 是否必須使用「remember_token」字段?
- 28. Mysql外鍵,必須在引用表或鍵中匹配刪除?
- 29. 不能分配「'str值'」:「詳細table.voucher_id」必須是「主表」實例
- 30. 我是否必須使用_ID作爲SQlite主鍵?它是否必須是一個INT? (Android Dev)
您是否對您的應用程序進行了簡介,以確定堆分配速度太慢,還是您只是在做出假設? – 2013-05-12 09:35:18
我的應用程序是矢量數學密集型的,我的Vector類是不可變的。 雖然我對分析工具並不是很熟悉,但我不知道該如何分配花費多少時間,所以我想我正在做假設(對於恥辱,嘿) – cabbagebot 2013-05-12 09:49:04
如果您需要極高的性能,您可以使用Vector類邏輯並將其移植到C++,然後使用JNI與您的類進行集成。這具有打破平臺獨立性的缺點,但如果它只是一小段代碼就可以。您可以爲大多數平臺提供「官方」編譯版本,並將.cpp文件與您的應用程序一起發佈,以便異國平臺的用戶可以自行編譯該庫。 – 2013-05-12 09:57:09