user12208242
user12208242

Reputation: 335

How does java store literals?

System.out.println(5678);

This literal is directly used in the printing statement. But does java store it directly in a memory or it creates an automatic variable and then stores it there? If the second case is to be true, what would happen if anyone happens to access that variable accidentally using the same variable name?

Upvotes: 3

Views: 1203

Answers (3)

Zabuzard
Zabuzard

Reputation: 25903

Explanation

Whatever Java does under the hood is completely hidden from the user and programmer.

As long as you are still writing Java code, it is impossible to mess with it. Might be a different story of course if you try to hookup the JVM process and inject C code, or interact with it via its native interface.

It is also completely up to the JVM how it actually handles this in memory. Memory management is fully hidden from the programmer in Java.


Bytecode

Variable inlined

That being said, let us take a look at the resulting byte code for this snippet (see javabytes.io or use javap -c Test.class):

// Source code
public class Test {
    public static void main(String [] args) {
        int value = 4000;
        System.out.println(value);

        System.out.println(5678);
    }
}

// Byte code
public class Test {
  public Test();
    Code:
       0: aload_0
       1: invokespecial #1    // Method java/lang/Object."<init>":()V
       4: return

  public static void main(java.lang.String[]);
    Code:
       0: sipush        4000
       3: istore_1
       4: getstatic     #2    // Field java/lang/System.out:Ljava/io/PrintStream;
       7: iload_1
       8: invokevirtual #3    // Method java/io/PrintStream.println:(I)V
      11: getstatic     #2    // Field java/lang/System.out:Ljava/io/PrintStream;
      14: sipush        5678
      17: invokevirtual #3    // Method java/io/PrintStream.println:(I)V
      20: return
}

As you see, both variants are actually the same. The sipush command loads the values directly, no sign of any variables at all.

sipush pushes a short directly onto the stack, from where it is then picked up by the invokevirtual which calls the print method (see Java bytecode instruction list for details).

Why is that the case? Well, the compiler is smart. It figured that the variable value serves no purpose and actually completely got rid of it. It changed the code to System.out.println(4000) and removed value completely.

Variable present

But we want to see some variables, so let us make it a bit more complex so that Java does not inline the variable anymore by introducing a dependency that can only be computed at run-time:

// Source code
public class Test {
    public static void main(String [] args) {
        int value = (int) System.currentTimeMillis();
        System.out.println(value);

        System.out.println(5678);
    }
}

// Byte code
public class Test {
  public Test();
    Code:
       0: aload_0
       1: invokespecial #1    // Method java/lang/Object."<init>":()V
       4: return

  public static void main(java.lang.String[]);
    Code:
       0: invokestatic  #2    // Method java/lang/System.currentTimeMillis:()J
       3: l2i
       4: istore_1
       5: getstatic     #3    // Field java/lang/System.out:Ljava/io/PrintStream;
       8: iload_1
       9: invokevirtual #4    // Method java/io/PrintStream.println:(I)V
      12: getstatic     #3    // Field java/lang/System.out:Ljava/io/PrintStream;
      15: sipush        5678
      18: invokevirtual #4    // Method java/io/PrintStream.println:(I)V
      21: return
}   

Finally we see some variable action! The variable is computed by the method, converted to int and then stored via istore_1. Then, it is loaded dynamically onto the stack by iload_1 and passed to the print method.

So via variable, we need to istore and iload it to the method. With a literal, we can directly load it to the method using sipush.

Upvotes: 6

UsamaAmjad
UsamaAmjad

Reputation: 4604

Short answer: No! you can not access them on compile time.

Java stores literals in permgen space memory and it is not accessible by variable names on compile time. It is also specific to JVM how they implement it.

For example if we talk about String literals in the below code, Java might store "sameSame" in some memory location (String Pool) and then use that for both methods instead of creating the same string twice.

private static String test1(){
    return "sameSame";
}

private static String test2(){
    return "sameSame";
}

Upvotes: 1

Botje
Botje

Reputation: 30860

I compiled the following test file:

class test {
    public static void main(String[] args) {
        System.out.println(5678);
        System.out.println("test string");
    }
}

Decompiling it with javap -c results in the following:

    public static void main(java.lang.String[]);
      Code:
         0: getstatic     #7                  // Field java/lang/System.out:Ljava/io/PrintStream;
         3: sipush        5678
         6: invokevirtual #13                 // Method java/io/PrintStream.println:(I)V
         9: getstatic     #7                  // Field java/lang/System.out:Ljava/io/PrintStream;
        12: ldc           #19                 // String test string
        14: invokevirtual #21                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
        17: return

If you add the -verbose flag it also prints the constant pool, where you can look up #19 and see that it is the string test string.

If you are interested in more such details: the JVM specification has many more details.

Upvotes: 2

Related Questions