int a = 1的内存

需要定义int a = 3; int b =3;这两个自动变量。编译器先处理int  a=3;首先在栈中创建一个变量为a的引用,然后查找栈有没有字面值为3的引用,没有找到,就开辟一个存放3这个字面值的地址,然后将a指向3的地址。接着处理int b=3;在创建完b这个引用变量后,由于在栈中已经有了3这个字面值,即将b直接指向3的地址。这样,就出现了a和b同事指向3的情况。 定义完a与b后,在令a=4,那么b不会等于4,而是等于3,。在编译器内部,遇到时,它就会中新搜索栈中是否有4这个字面值,如果没有,重新开辟地址存放4的值。如果已经有就直接将a指向这个地址,因此a的值改变不会影响b的值。 

Java代码是如何run起来的

在使用现代IDE开发过程中,从我们编写代码到运行结果一切显得很简单,而其中过程究竟是怎样的呢?我整理了一下,大致的步骤如下:

  • 编译,java代码编译成字节码class文件
  • 加载,将class文件加载到JVM中,存放在方法区(Method Area)
  • 执行,执行以方法为单位,一个方法对应一个Java栈(字节码到机器码)

我们知道,平时我们编写的J代码是用Java语言,而Java代码需要通过编译成字节码才能被JVM所运行,这也是Java跨平台的原因,由JVM屏蔽底层差异,而字节码是无法被操作直接执行的,所以,JVM需要把字节码翻译成机器码,这个时候才算是真正的run起来

JVM如何运行成员变量int a=1;

例如,有这样的代码:

public class Foo {
    private int a = 1;
    public int getValue(){
        return a;
    }
}

 反编译,javap -v -p -l Foo.class,可以知道:



Classfile /D:/execise/demo/target/test-classes/com/sevenlin/demo/Foo.class
  Last modified 2019-9-12; size 383 bytes
  MD5 checksum 37b0e24496211bdc65a4579b015a83f1
  Compiled from "Foo.java"
public class com.sevenlin.demo.Foo
  minor version: 0
  major version: 52
  flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
   #1 = Methodref          #4.#18         // java/lang/Object."<init>":()V
   #2 = Fieldref           #3.#19         // com/sevenlin/demo/Foo.a:I
   #3 = Class              #20            // com/sevenlin/demo/Foo
   #4 = Class              #21            // java/lang/Object
   #5 = Utf8               a
   #6 = Utf8               I
   #7 = Utf8               <init>
   #8 = Utf8               ()V
   #9 = Utf8               Code
  #10 = Utf8               LineNumberTable
  #11 = Utf8               LocalVariableTable
  #12 = Utf8               this
  #13 = Utf8               Lcom/sevenlin/demo/Foo;
  #14 = Utf8               getValue
  #15 = Utf8               ()I
  #16 = Utf8               SourceFile
  #17 = Utf8               Foo.java
  #18 = NameAndType        #7:#8          // "<init>":()V
  #19 = NameAndType        #5:#6          // a:I
  #20 = Utf8               com/sevenlin/demo/Foo
  #21 = Utf8               java/lang/Object
{
  private int a;
    descriptor: I
    flags: ACC_PRIVATE
​
  public com.sevenlin.demo.Foo();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=2, locals=1, args_size=1
         0: aload_0
         1: invokespecial #1                  // Method java/lang/Object."<init>":()V
         4: aload_0
         5: iconst_1
         6: putfield      #2                  // Field a:I
         9: return
      LineNumberTable:
        line 7: 0
        line 9: 4
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0      10     0  this   Lcom/sevenlin/demo/Foo;
​
  public int getValue();
    descriptor: ()I
    flags: ACC_PUBLIC
    Code:
      stack=1, locals=1, args_size=1
         0: aload_0
         1: getfield      #2                  // Field a:I
         4: ireturn
      LineNumberTable:
        line 12: 0
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       5     0  this   Lcom/sevenlin/demo/Foo;
}
SourceFile: "Foo.java"

从中可以看出,如果我们执行代码new Foo().getValue()的话

  • 成员变量a在Foo构造函数中被初始化
  • Foo实例会在堆中申请内存
  • iconst_1常量1通过putfield操作初始化成员变量a

那么,至此这个问题可以如此回答:

成员变量 int a = 1, a作为变量名,在JVM中是以代码的形式存在,存放在方法区,当有线程执行到该代码的时候,会加载该代码进行执行,而1作为参数 a 的值在运行时存放在堆内存中,a指向该内存

如果int a=1;作为局部变量存在呢?

public class Foo {
    public int getValue(){
        int a = 1;
        return a;
    }
}

 反编译如下(截取getValue部分)

public int getValue();
  descriptor: ()I
  flags: ACC_PUBLIC
  Code:
    stack=1, locals=2, args_size=1
       0: iconst_1
       1: istore_1
       2: iload_1
       3: ireturn
    LineNumberTable:
      line 11: 0
      line 12: 2
    LocalVariableTable:
      Start  Length  Slot  Name   Signature
          0       4     0  this   Lcom/sevenlin/demo/Foo;
          2       2     1     a   I

可以知道,对于局部变量,a存在局部变量表中,在这个例子中,getValue()的声明周期就是该方法对应的Java栈,执行到a=1时会将iconst_1放到操作数栈,然后通过istore_1存放局部变量变中1的位置,而从中可以知道,a的类型为int,所以在变量槽(Solt)中存在的就是数值1

所以,int a=1为局部变量的时候,这个时候a同样存在方法区的代码中,运行时a存在该方法对应的栈帧的局部变量表中,而该变量表中a的值为1,所以1存在栈内存中。

 

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
THE END
分享
二维码
< <上一篇
下一篇>>