2011-04-07 60 views
4

在,我保持一個項目字符串變量JVM的優化,我發現下面在方法

class Test{ 

public void fn(){ 
    String METHOD_NAME = "fn"; 
    ... 
    sysout("In " + METHOD_NAME); 
} 
} 

該計劃將無限期運行和方法「FN顯示與方法「FN」類似於一個Java類'被連續調用並且頻率非常高。問題是

  1. 變量METHOD_NAME會在每次調用fn()時被創建嗎?
  2. JVM會進行一些優化,以便在下次調用fn()時變量METHOD_NAME不會被垃圾收集和重用嗎?
  3. 如果我將該變量設爲公共靜態最終結果,會有性能改進嗎?
    (其實有,我想知道,如果它的價值就改變所有的人這麼多這樣的功能)

(我猜串池在這裏踢球一定的作用)

謝謝, 基蘭莫漢

+1

順便說一句:IO通常比創建對象要貴得多。除非你可以避免IO,或者有很多創建的對象可以優化,否則它可能不會有太大的區別。 – 2011-04-07 10:25:04

回答

6

是的,變量METHOD_NAME將在您每次輸入方法時創建,但這是非常非常便宜的操作(實際上創建2個變量與創建1一樣昂貴)。

(即String對象)"fn"被重新創建,但將來自字符串常量池。

然而,表達"In " + METHOD_NAME將被重新計算,並導致每次創建一個新的String對象,因爲它不是一個compile time constant expression

如果METHOD_NAME其中static final,那麼該表達式也是編譯時間常數,因此將來自常量池。

+0

+1類似於清晰度 – 2011-04-07 08:32:44

+0

只是爲了完成:'「In」+ METHOD_NAME'也會導致創建一個新的StringBuilder! – 2011-04-07 08:33:07

+1

@Carlos:這是正確的(如果'METHOD_NAME'不是一個常量(即不是'static final'))。 – 2011-04-07 08:42:11

-2

雅去公共靜態最後,這將提高性能。

+0

@voted down:什麼是在我的回答worng – developer 2011-04-07 08:13:33

+0

你的答案是質量很低,最有可能不正確。 – 2011-04-09 04:56:23

2

「fn」將被實施。因此,同一個對象會一次又一次地被使用。

在最壞的情況下,你可以通過僅僅指剛更換:

String METHOD_NAME = "fn".intern(); 

雖然我認爲它是不必要的。

使其成爲公共靜態最終是好的。

+0

不要在字符串上使用'intern()'!它總是**不必要的。每個定義。 – 2011-04-07 08:12:59

+0

'intern'可能比較昂貴(需要搜索池中的字符串),不建議在循環中使用(儘管是不必要的) – 2011-04-07 08:38:09

0

字符串文字被放置在常量池中。將字符串放入靜態最終沒有任何意義 - 這種行爲由JLS保證。

(是的,該字符串也將被拘留,雖然這不是特別相關的爲您解決問題)

3

變量不是垃圾收集 - 對象。

「fn」是一個字符串文字,所以它會被設置爲。它不會被垃圾回收(至少在ClassLoader處於活動狀態時;不確定每個CL有一個實習池還是一個用於整個JVM,但可能不相關),並且每次調用時都會使用相同的字符串對象。

如果您將其設爲公共靜態最終將有肯定是一種改進,因爲連接可以由編譯器而不是在執行時完成。

如果你讓最終的方法(即仍然爲局部變量),即可能有同樣的效果 - 我不知道。

+0

檢查字節碼:在循環內部進行最終處理會產生相同的效果 - 編譯時無需連接 - 但仍有一個賦值給變量(可能被JIT消除)。 – 2011-04-07 10:49:38

0

每次調用fn()時,變量METHOD_NAME都會被創建嗎?

該變量將被「創建」(更好的「設置」),但字符串不是(因爲它是駐留在JVM的字符串池中的內部化字符串)。所以這只是對同一個字符串的新引用。

將在JVM做了一些優化,使得可變METHOD_NAME沒有垃圾回收和再利用接下來的時間FN()被調用

變量METHOD_NAME僅僅是一個參考的名稱。引用的字符串可能駐留在字符串池中。

如果我將變量設爲公共靜態最終會有性能改進嗎?

可能有,但我寧願忽略它,因爲它將是微型優化。

實際上,爲了獲得較小的性能提升,您應該考慮是否有必要每次都打印日誌語句,尤其是在生產環境中可能太冗長的情況下。

1

據我所知,METHOD_NAME - String'fn'的引用將在fn()的每次調用中分配。但是,字符串'fn'的對象應該被分配一次,因爲它是一個字符串常量,並將被放入字符串池中。

用公共靜態最終替換它可能是一個好主意,但它是用於編程風格而不是性能問題。