2017-08-30 35 views
1

在有關靜態像thisthis一些文章和教程,據說使用靜態還是不錯的內存管理,因爲靜態變量類地區的類加載的時間變內存只有一次。是否使用Static更好地進行內存管理?

但我的朋友告訴我,靜態方法保存在堆棧中,因爲管理堆比堆棧更容易,垃圾收集器只能在堆上運行,只要應用程序運行堆棧不會清理,請嘗試使用靜態方法儘可能少。

注:

我讀過的計算器約堆棧存儲器同樣的問題,但我沒有得到太多的,因爲他們是一些多麼複雜和專業的使用「的PermGen空間」,換句話說我不不知道。

我想讓別人簡單地解釋一下,如果我的朋友提前是否正確?

而且我知道它依賴,以爲我既可以靜態或不帶靜電的方法進行設計。內存管理正在談論哪一個會更好?

+3

他們都錯了。在適合您的設計時使用它,否則不要使用它。內存管理不應該是你主要關心的問題。 – shmosel

+0

我認爲這取決於。 – Willmore

+0

靜態成員不會堆疊。 我認爲它保留在PermGen。 [鏈接](http://www.journaldev。java/jvm-memory-model-memory-management-in-java) – MehmanBashirov

回答

4

答案是:問這個問題意味着你花時間和精力在錯誤的地方。

的關鍵角色去表現良好的Java應用程序:想出一個優雅的OOP設計,實現了一個直接的方式您的要求。

你必須明白,「Java性能魔術」幾乎完全在運行時間處由Just-in-Time編譯器工作。 JIT最適合那些我們認爲是Java中的「最佳實踐」的常用模式。

試圖想出「特殊」的想法,比如「讓靜態使用靜態」甚至可能導致最終性能變差 - 因爲您的「特殊」代碼阻止JIT以最佳方式工作。

所以:分別信任JIT和GC。並確保這些工具能夠以「最佳」方式工作......做其他人都在做的事情!

不要讓這種過早優化的想法毀了你的OOP設計。即使您的應用程序會陷入罕見的類別,需要密集低水平優化 - 那麼就只有一個你的方法:學習GC和JIT 的工作深入

換句話說,這樣的問題並不真正問題。含義:

    當然
  • 你避免徹底愚蠢的錯誤,但
  • ,否則你做擔心內存或性能主題除非你的手(例如有真正問題與應用程序需要太許多記憶或顧客抱怨你)。

然後 - 當你進入一個「真正」的問題:那麼你必須輪廓您的應用程序,以瞭解問題的根源。再說一次:你不允許這種過早的(未受教育的)優化思想以負面的方式影響你的設計。

而且正如評論意味着我不夠清楚:當你有一個真正的記憶問題,那麼你絕對必須理解像「燙髮一代」的術語。因爲那你必須瞭解細節 GC的工作原理。嚴重的是:相信這裏的人告訴你,關鍵字在創建「高效內存」應用程序時不起任何重要作用。

+1

內存管理不是我主要關心的問題,但我在想什麼當我有權選擇時,我更喜歡一種方式,嘗試不使用靜態方法或沒有問題,或者更好地使用它們的內存? – user5621266

+0

我想你還是沒有明白我的觀點。請參閱我剛添加的段落。 – GhostCat

+0

我的經驗是,當客戶開始抱怨時,修復與內存管理相關的糟糕設計決策爲時已晚 - 早期做出的決策過於頑固,無法改變。在這種情況下通常會發生的情況是臨時性的問題會被用來解決設計不足的問題。然而,我同意,如果你認爲內存管理可能是你應用程序中的一個重要因素,那麼就有必要對JVM在這方面的工作方式有一個非常詳細和透徹的理解。依靠模糊的經驗法則不會有太大的幫助。 –

2

當程序第一次運行時,靜態變量的內存分配只出現一次。 如果您在一個類中使用它,則僅創建一個由該類的每個對象共享的實例。 因此內存消耗少。在java8之前,靜態方法和變量存儲在PERMGEN空間中。但是現在它們已經引入了新的內存空間,現在稱爲METASPACE,這是所有類方法,類和常量池的存儲位置。 有關METASPACE的更多詳細信息,請訪問:「https://dzone.com/articles/java-8-permgen-metaspace

+0

堆棧內存的作用是什麼? – user5621266

3

簡短回答是你的朋友是錯的。 class對象本身(例如java.lang.Class<T>的實例未分配到堆棧上 Java在加載類時會加載它,並且在加載它們的函數結束時不會卸載它們,因此無法進入堆棧。所有線程都訪問相同的類對象,但每個線程都有自己的堆棧空間。

警告:本答案的其餘部分討論JVM實現細節和垃圾收集內存管理,大多數應用程序不需要考慮這些事實,不要依賴他們的程序正確性,因爲他們可以並且從發佈變爲發佈。

許多現代JVM使用世代垃圾回收器,因爲系統加載的類將不會被卸載,因此可以將它們放在一個稱爲'永久代(PermGen)'的區域中,該區域在Oracle中由Java替換,並由元數據空間代替,該元數據包含問題引用的類元數據。但是請確認這些是Oracle JVM的實現細節,而不是Java規範的一部分。

另一個可能的混淆是,這一切都適用於類直接需要的空間,它是靜態引用,但不是那些引用引用的內容。

class Sample { 
    private static BigThing biggie=new BigThing(10000); 
} 

在這個例子中biggie引用會像別的堆上創建的對象。事實上,這裏沒有聲明final,並且可以引用任何在執行時創建的對象,因爲它可以被重新分配。

下面是關於這一主題的相對最近的一篇文章:

https://blogs.oracle.com/poonam/about-g1-garbage-collector,-permanent-generation-and-metaspace

請注意,JVM的這方面一直受到改變和調整多年來但(據我所知)持平Java 9.

相關問題