java jvm在哪里,int a = 1,到底存在于JVM的哪里

我是谁,我在哪? QAQ

学习本篇文章需要对JVM内存结构和类加载机制有一定了解~

int作为Java八大基本数据类型之一,大家最熟悉不过了。

如果说我们学习java写的第一行代码是

System.out.println("Hello World");

那么我们学习的第二行就是这个了吧

int a = 1;

那到底a存放于哪里,1又放在哪里了呢?

答案当然不会是唯一的,要是唯一的我还会专门写嘛哈哈!

先说下答案,你答对了么?

1 a作为类的成员变量,存放于方法区中;1保存在堆(Heap)的实例中

2 a作为方法局部变量,存放于Java虚拟机栈(JVM Stacks)的局部变量表中;1也保存在栈内存中。

一 作为类的成员变量

有如下代码

public class IntTest {

int a = 1;

}

我们通过javap反编译class文件

javap -v -p -l IntTest

Classfile /Users/xxxxx/IdeaProjects/demo/target/classes/com/example/demo/IntTest.class

Last modified 2020-4-20; size 315 bytes

MD5 checksum 93d441915a8d7bc6db8efbbd7cff6158

Compiled from "IntTest.java"

public class com.example.demo.IntTest

// 4个字节用于存储版本号

// 前2个字节存储次版本号

minor version: 0

// 后2个存储主版本号

major version: 52

// ACC_PUBLIC:是否为Public类型 ACC_SUPER:是否允许使用invokespecial字节码指令的新语义

flags: ACC_PUBLIC, ACC_SUPER

// 用于存放常量的常量池,主要存储了字面量以及符号引用

Constant pool:

#1 = Methodref #4.#16 // java/lang/Object."":()V

#2 = Fieldref #3.#17 // com/example/demo/IntTest.a:I

#3 = Class #18 // com/example/demo/IntTest

#4 = Class #19 // 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/example/demo/IntTest;

#14 = Utf8 SourceFile

#15 = Utf8 IntTest.java

#16 = NameAndType #7:#8 // "":()V

#17 = NameAndType #5:#6 // a:I

#18 = Utf8 com/example/demo/IntTest

#19 = Utf8 java/lang/Object

// 方法表集合

{

int a;

descriptor: I

flags:

public com.example.demo.IntTest();

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 3: 0

line 4: 4

LocalVariableTable:

Start Length Slot Name Signature

0 10 0 this Lcom/example/demo/IntTest;

}

// 源码文件名称

SourceFile: "IntTest.java"

如果我们执行new IntTest();操作,a变量会在构造函数中初始化,iconst_1通过putfield赋予了值。

JVM在加载Class时,创建instanceKlass,表示其元数据,包括常量池、字段、方法等,存放在方法区,所以成员变量a就在方法区咯。

在new一个对象时,JVM创建instanceOopDesc,来表示这个对象,存放在堆区,其引用,存放在栈区;所以1存放在堆中。

ps:不懂可以咕鸽"oop_klass模型",或者移步我的另一篇文章。

二 作为方法局部变量

public class IntTest {

public void getValue() {

int a = 1;

}

}

反编译如下

public void getValue();

descriptor: ()V

flags: ACC_PUBLIC

Code:

stack=1, locals=2, args_size=1

0: iconst_1

1: istore_1

2: return

LineNumberTable:

line 5: 0

line 6: 2

LocalVariableTable:

Start Length Slot Name Signature

0 3 0 this Lcom/example/demo/IntTest;

2 1 1 a I

当代码执行到 int a = 1;的时候JVM会

iconst_1 int型常量1进栈

istore_1 栈顶int数值存入第2局部变量

所以a作为局部变量会放在局部变量表中,1则是虚拟机在栈空间内开辟了一处地址存放,a指向1,且1在栈中可以被其他局部变量共享,int b = 1; 中b发现栈内存中已经有了1,也指向1

现在你了解了么QAQ

以上均为个人理解,如有不足之处,欢迎在评论区留言。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值