简体   繁体   中英

Where are memory addresses stored in Java

Where are memory address stored in Java ? What I am trying to understand is how something like the following is stored. I already know the difference between stack and heap but trying to dig a layer deeper than that.

int i = 5;

Is i stored separately and 5 stored separately, and then a mapping is established?

Similarly, we say that for a 32 bit version one can have at most 4 GB RAM (much less in reality), where are the memory addresses of all these memory blocks are stored ?

What I am trying to understand is how something like the following is stored.

It depends on where that int i = 5; is:

Local Variable

If that's within a method and therefore i is a local variable, then 5 is stored as a local on the stack ( i isn't "stored" anywhere, the bytecode generator just remembers where on the stack i is). Bytecode has specific instructions for interacting with local variables, including some quite efficient dedicated no-args versions, such as iload_0 which loads an int from "local variable 0". (Those go through iload_3 , and then there's a version taking an arg, iload followed by an index.)

Consider this class:

public class Example {

    public static final void main(String[] args) {
        int i = 5;

        System.out.println(i);
    }
}

Here's the bytecode for that (you can get this by compiling it and then doing javap -c Example ), with notes to the right:

public class Example {
  // ...omitted constructor stuff...

  public static final void main(java.lang.String[]);
    Code:
      // The `int i = 5;` line:
       0: iconst_5               // Load the constant 5 onto the stack
       1: istore_1               // Store it in local variable 1

      // The `System.out.println(i);` line:
       2: getstatic     #2       // Get the static field java/lang/System.out:Ljava/io/PrintStream onto the stack
       5: iload_1                // Load int variable 1 on the stack
       6: invokevirtual #3       // Call java/io/PrintStream.println, which gets
                                 // the stream and what to write from the stack
       9: return
}

Note the two different uses of the stack there: The "locals" are on the part of the stack that the method allocated itself for locals (since it knows in advance how many there are), and then there's the dynamic part following that that it uses for passing information into methods and such.

Instance field

If that's within a class definition and therefore i is an instance field of the class, i is part of the structure that Java reserves (either on the stack or heap, sometimes moving between them) for the instance.

Bytecode doesn't really shed a lot of light on this, but consider this class:

public class Example {

    int i = 5;

    public static final void main(String[] args) {

        Example ex = new Example();
        System.out.println(ex.i);
    }
}

Here's the bytecode for that:

public class Example {
  // Here's the instance field
  int i;

  // ...omitted the constructor stuff...

  public static final void main(java.lang.String[]);
    Code:
      // Create our Example instance and save it in a local variable
       0: new           #3
       3: dup
       4: invokespecial #4
       7: astore_1

      // The `System.out.println(ex.i)` line:
       8: getstatic     #5     // Get the java/lang/System.out:Ljava/io/PrintStream field
      11: aload_1              // Get `ex` onto the stack
      12: getfield      #2     // Get the value of field `i` onto the stack from the instance we just put on the stack (pops the instance off)
      15: invokevirtual #6     // Call java/io/PrintStream.println, which
                               // again gets the stream to write to and
                               // what to write from the stack
      18: return
}

Where are memory address stored in Java ?

In Java references are not just memory addresses and due to compressed oops, they are used very rarely for Java related data.

What I am trying to understand is how something like the following is stored.

It is worth remembering that the JVM is a virtual machine, you can say how it is notionally stored in byte code but the code itself goes through multiple stages of optimisation and it could change each time.

Also the JVM is very good at optimising away code which doesn't do anything so in many trivial cases the answer is; nowhere, the code has been inlined away to nothing.

I already know the difference between stack and heap but trying to dig a layer deeper than that.

 int i = 5;

Is i stored separately and 5 stored separately, and then a mapping is established?

At runtime, it is a good chance the value has been inlined out of existence. However, it could be on the stack, the heap or both depending on the context.

Similarly, we say that for a 32 bit version one can have at most 4 GB RAM (much less in reality), where are the memory addresses of all these memory blocks are stored ?

In the 32-bit version you can only use the largest continuous region available as the heap. This is limited to about 1.4 GB on windows and about 3 GB on Unix.

In the 64-it version, it generally uses 32-bit references which go through a translation to allow you to address up to 32 GB (Java 7) and 64 GB (Java 8) Without Compressed Oops you can address a 48-bit address space on most OSes (limited by the hardware and OS)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM