Lenik
Lenik

Reputation: 14458

Do long type names impact on performance?

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

Answers (3)

Neil Coffey
Neil Coffey

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

Tiago Peczenyj
Tiago Peczenyj

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

Ted Hopp
Ted Hopp

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

Related Questions