java a<<1_java中,成员变量 int a = 1, a存在哪, 1存在哪 (存在JVM哪)?

看了下这个问题,其实自己也是深有感触,相信大部分编程初学者都会有这样的疑问,会好奇自己编写的代码是如何run起来的,刚学JVM内存模型的时候会好奇自己编写的代码在内存中是怎样子的,当初我也有这种疑问。

要回答这个问题需要对Java代码是如何被JVM运行的,并且会JVM内存模型,内存分配有一定了解。

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."":()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

#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 // "":()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."":()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存在栈内存中。

总结

对于变量a,不能说存在哪儿,要理解变量,变量只是编程中一个抽象的概念,它只是对内存空间的一个引用,能够通过变量访问对应的数值,而该数值才是我们所关心的数据

参考:Java基本数据类型内存分配 - 澡堂麦霸 - 博客园​www.cnblogs.com

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值