Reputation: 14458
Type name like com.example.Dog
will be compiled to com/example/Dog
in the .class file. How will most JVM optimize it? It seems longer type names (or member names) need more string compares.
Upvotes: 6
Views: 529
Reputation: 21795
This depends partly on whether the actual precise method can be resolved at the time of JIT compilation. If it can, then it is possible for the compiled code simply to branch to the relevant code. You can see evidence for Hotspot doing so in these timings for final vs non-final method calls, for example. In fact, there is no such optimisation specifically for final methods (this is a common misconception I have found among developers). But as these figures show, there is an optimisation for cases where the precise method can be identified, final or not.
If the precise method cannot be identified, then the VM could at least operate on hash codes of method signatures so that once the hash code had been calculated once for the call being made from a given bytecode offset of a given method, it wouldn't need to be calculated again. I confess I haven't looked to see if Hotspot or other JVMs actually do this, but in principle it would seem a blindingly obvious thing to do.
Upvotes: 1
Reputation: 4623
the java compiler generate bytecode, there is no string comparison.
check this class with javap and see the bytecode.
For example, this
class A extends java.lang.Object{
static final boolean $assertionsDisabled;
A();
public static void main(java.lang.String[]);
static {};
}
turn this
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
}
internally the jvm uses numerical ids. there is no difference between long and short variable names.
edit: add -l output
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
}
and add a -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 ]
}
Upvotes: 6
Reputation: 234795
Long type (class and interface) names take up room in the symbol tables. The names are used at linking time as described in detail in Chapter 5 of the Java Virtual Machine Specification. Once all this linking is done, the names have no effect on run-time performance unless you are using reflection.
Upvotes: 9