類型名稱如com.example.Dog
將在.class文件中編譯爲com/example/Dog
。大多數JVM如何優化它?似乎更長的類型名稱(或成員名稱)需要更多的字符串比較。長類型名稱會影響性能嗎?
回答
長型(類和接口)的名字佔據空間的符號表。鏈接時使用名稱,詳見Chapter 5 of the Java Virtual Machine Specification。一旦完成了所有這些鏈接,除非您使用反射,否則這些名稱對運行時性能沒有影響。
TL; DR在正常情況下「效果不明顯」。 –
@Stephen - JVM規範確實是密集讀取。我認爲你表達了完全正確的外賣。 (雖然我會使用「最」而不是「正常」;誰知道這些天來什麼是正常的:))。 –
java編譯器生成字節碼,沒有字符串比較。
用javap檢查此類並查看字節碼。
例如,這
class A extends java.lang.Object{
static final boolean $assertionsDisabled;
A();
public static void main(java.lang.String[]);
static {};
}
反過來,這
class A extends java.lang.Object{
static final boolean $assertionsDisabled;
A();
Code:
0: aload_0
1: invokespecial #1; //Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String[]);
Code:
0: getstatic #2; //Field $assertionsDisabled:Z
3: ifne 14
6: new #3; //class java/lang/AssertionError
9: dup
10: invokespecial #4; //Method java/lang/AssertionError."<init>":()V
13: athrow
14: getstatic #5; //Field java/lang/System.out:Ljava/io/PrintStream;
17: ldC#6; //String hi
19: invokevirtual #7; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
22: return
static {};
Code:
0: ldc_w #8; //class A
3: invokevirtual #9; //Method java/lang/Class.desiredAssertionStatus:()Z
6: ifne 13
9: iconst_1
10: goto 14
13: iconst_0
14: putstatic #2; //Field $assertionsDisabled:Z
17: return
}
內部JVM使用數值的ID。長和短變量名之間沒有區別。
編輯:添加-l輸出
Compiled from "A.java"
class A extends java.lang.Object{
static final boolean $assertionsDisabled;
A();
Code:
0: aload_0
1: invokespecial #1; //Method java/lang/Object."<init>":()V
4: return
LineNumberTable:
line 3: 0
public static void main(java.lang.String[]);
Code:
0: getstatic #2; //Field $assertionsDisabled:Z
3: ifne 14
6: new #3; //class java/lang/AssertionError
9: dup
10: invokespecial #4; //Method java/lang/AssertionError."<init>":()V
13: athrow
14: getstatic #5; //Field java/lang/System.out:Ljava/io/PrintStream;
17: ldC#6; //String hi
19: invokevirtual #7; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
22: return
LineNumberTable:
line 6: 0
line 7: 14
line 8: 22
static {};
Code:
0: ldc_w #8; //class A
3: invokevirtual #9; //Method java/lang/Class.desiredAssertionStatus:()Z
6: ifne 13
9: iconst_1
10: goto 14
13: iconst_0
14: putstatic #2; //Field $assertionsDisabled:Z
17: return
LineNumberTable:
line 3: 0
}
,並添加-verbose -s
Compiled from "A.java"
class A extends java.lang.Object
SourceFile: "A.java"
minor version: 0
major version: 50
Constant pool:
const #1 = Method #10.#23; // java/lang/Object."<init>":()V
const #2 = Field #8.#24; // A.$assertionsDisabled:Z
const #3 = class #25; // java/lang/AssertionError
const #4 = Method #3.#23; // java/lang/AssertionError."<init>":()V
const #5 = Field #26.#27; // java/lang/System.out:Ljava/io/PrintStream;
const #6 = String #28; // hi
const #7 = Method #29.#30; // java/io/PrintStream.println:(Ljava/lang/String;)V
const #8 = class #31; // A
const #9 = Method #32.#33; // java/lang/Class.desiredAssertionStatus:()Z
const #10 = class #34; // java/lang/Object
const #11 = Asciz $assertionsDisabled;
const #12 = Asciz Z;
const #13 = Asciz <init>;
const #14 = Asciz ()V;
const #15 = Asciz Code;
const #16 = Asciz LineNumberTable;
const #17 = Asciz main;
const #18 = Asciz ([Ljava/lang/String;)V;
const #19 = Asciz StackMapTable;
const #20 = Asciz <clinit>;
const #21 = Asciz SourceFile;
const #22 = Asciz A.java;
const #23 = NameAndType #13:#14;// "<init>":()V
const #24 = NameAndType #11:#12;// $assertionsDisabled:Z
const #25 = Asciz java/lang/AssertionError;
const #26 = class #35; // java/lang/System
const #27 = NameAndType #36:#37;// out:Ljava/io/PrintStream;
const #28 = Asciz hi;
const #29 = class #38; // java/io/PrintStream
const #30 = NameAndType #39:#40;// println:(Ljava/lang/String;)V
const #31 = Asciz A;
const #32 = class #41; // java/lang/Class
const #33 = NameAndType #42:#43;// desiredAssertionStatus:()Z
const #34 = Asciz java/lang/Object;
const #35 = Asciz java/lang/System;
const #36 = Asciz out;
const #37 = Asciz Ljava/io/PrintStream;;
const #38 = Asciz java/io/PrintStream;
const #39 = Asciz println;
const #40 = Asciz (Ljava/lang/String;)V;
const #41 = Asciz java/lang/Class;
const #42 = Asciz desiredAssertionStatus;
const #43 = Asciz ()Z;
{
static final boolean $assertionsDisabled;
Signature: Z
A();
Signature:()V
LineNumberTable:
line 3: 0
Code:
Stack=1, Locals=1, Args_size=1
0: aload_0
1: invokespecial #1; //Method java/lang/Object."<init>":()V
4: return
LineNumberTable:
line 3: 0
public static void main(java.lang.String[]);
Signature: ([Ljava/lang/String;)V
LineNumberTable:
line 6: 0
line 7: 14
line 8: 22
Code:
Stack=2, Locals=1, Args_size=1
0: getstatic #2; //Field $assertionsDisabled:Z
3: ifne 14
6: new #3; //class java/lang/AssertionError
9: dup
10: invokespecial #4; //Method java/lang/AssertionError."<init>":()V
13: athrow
14: getstatic #5; //Field java/lang/System.out:Ljava/io/PrintStream;
17: ldC#6; //String hi
19: invokevirtual #7; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
22: return
LineNumberTable:
line 6: 0
line 7: 14
line 8: 22
StackMapTable: number_of_entries = 1
frame_type = 14 /* same */
static {};
Signature:()V
LineNumberTable:
line 3: 0
Code:
Stack=1, Locals=0, Args_size=0
0: ldc_w #8; //class A
3: invokevirtual #9; //Method java/lang/Class.desiredAssertionStatus:()Z
6: ifne 13
9: iconst_1
10: goto 14
13: iconst_0
14: putstatic #2; //Field $assertionsDisabled:Z
17: return
LineNumberTable:
line 3: 0
StackMapTable: number_of_entries = 2
frame_type = 13 /* same */
frame_type = 64 /* same_locals_1_stack_item */
stack = [ int ]
}
我認爲這一點可能與局部變量有關,但數字id不用於任何非私有(類名或任何可見成員)。如果您查看實際的二進制數據,您確實會看到許多完全限定的類名稱。完全限定的類名是唯一能夠完全消除類的歧義的類,因此它必須被編譯到類中。現在,類文件格式/ JVM是否在一個類中優化了這個問題將是一個相關的答案。它使用查找表嗎? –
糟糕,我錯了'-l'的作用,它是行號和* local變量*表,而不是象我在刪除的註釋中所說的符號表。 –
你認爲在 - 動詞,對不對? –
這部分取決於實際的精確方法是否可以在JIT編譯時解決。如果可以的話,編譯後的代碼可以簡單地分支到相關的代碼。例如,您可以在final vs non-final method calls的這些時間點看到Hotspot這樣做的證據。事實上,最終方法沒有特別的優化(這是我在開發人員中發現的常見誤解)。但是,正如這些數字顯示的那樣,是的一種優化,用於精確方法可以被識別,最終與否的情況。
如果精確的方法不能被識別,那麼VM可以至少在散列碼方法簽名操作,使得一旦散列碼已被用於該呼叫計算一次被從給定的字節碼的給定的偏移量由方法,它不需要再次計算。我承認,我沒有看到Hotspot或其他JVM是否真的這樣做,但原則上這似乎是一個非常明顯的事情。
- 1. Perl:長包名稱會影響解析性能嗎?
- 2. NSClassFromString會影響性能嗎?
- 3. CSS類名稱長度是否影響瀏覽器性能?
- 4. 使用完全限定名稱會影響性能嗎?
- 5. 數據類型長度是否會影響性能?
- 6. 長時間使用CSS類名會對性能產生影響嗎?
- 7. 做數據類型選擇會影響性能嗎?
- 8. 數據庫字段名稱長度對性能的影響?
- 9. 名稱長度是否影響Redis的性能?
- 10. Oracle中的大型數據類型長度性能影響?
- 11. 急於加載會影響性能嗎?
- 12. django adminplus會影響性能嗎?
- 13. BindingExpression(path)錯誤會影響性能嗎?
- 14. Oracle數據泵會影響性能嗎?
- 15. Sysout會影響tomcat的性能嗎?
- 16. Javascript SetTimeOut會影響頁面性能嗎?
- 17. 很多IFRAME會影響性能嗎?
- 18. 使用jaxb XMLAdapter會影響性能嗎?
- 19. 是否爲表指定模式名稱會影響性能?
- 20. 導入更多名稱空間是否會影響性能?
- 21. 在代碼文件中添加更多名稱空間會影響性能嗎?
- 22. 在Java中使用泛型會影響性能嗎?
- 23. setTimeout()會影響性能
- 24. 表名或列名長度是否影響性能?
- 25. 快捷類影響性能?
- 26. 對象屬性名稱的長度是否會影響內存使用情況?
- 27. 您使用AWSDBProxy嗎?擴展時性能會受到影響嗎?
- 28. Java靜態屬性會影響性能嗎?
- 29. 自動屬性會影響運行時性能嗎?
- 30. 長而複雜的模板成員方法會影響性能嗎?
爲什麼-1?這是一個完全合法的問題。 – kaoD