jvm内存结构
想要了解Java对象在内存之中存储,首先要先了解jvm的的内存结构。这里大概介绍一下jvm的内存模型
--摘自彻底理解JVM内存模型 - 知乎 (zhihu.com)
这是一张非常经典的jvm内存结构图。
线程栈:程序运行时每调用的一个方法就会在栈中开辟一块内存空间,称为栈帧,栈帧内包含局部变量表,操作数栈(一些取值赋值操作的地方),动态链接,方法出口等。局部变量就保存在局部变量表之中,当然局部变量表也是一个栈结构。
堆:堆是jvm结构中最大的一块,主要用来保存Java对象。
方法区:类被类加载器会生成各类信息,类的方法代码,变量名,方法名,访问权限,返回值,静态变量,运行时常量池等等。
详解
package com.suancaiyu.student;
public class Student {
public String name;
public int age;
public int score;
public String getName() {
return name;
}
public Student(String name, int age, int score) {
this.name = name;
this.age = age;
this.score = score;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public int getScore() {
return score;
}
public void setScore(int score) {
this.score = score;
}
}
package com.suancaiyu.student;
public class text {
public static void main(String[] args) {
Student tom=new Student("张三",20,80);
System.out.println(tom.age);
}
}
这里我们准备了一个Student类,并且在text类main方法里面new了一个Student对象如何引用它的一个属性值。
变量名
在理解栈内存的之前我们先要知道一个概念,变量是什么,变量名是地址的映射,比如 int a=10;
10这个数据存储在栈内存之中,假设他的地址是Ox73800004,那么a就是这个地址的映射,存在一个映射函数将这个地址值映射成为a。
例子详解
启动main方法,main方法被压入线程栈,生成栈帧,声明一个Student类型的变量,变量tom被压入局部变量表之中(也是栈结构),执行new方法会在堆内存声明一块内存空间用于保存student对象。
当执行Student tom=new Student()时,jvm会在内存之中生成这样的一个结构。
栈内存中保存的是Java对象在堆内存的起始地址,Java对象由mark word,class指针以及自身字段组成,mark word和class指针是由jvm自动给我们生成,mark word占4个字节里面存储一些锁信息,class指向方法区内的Class 对象,这也是为什么实例对象上都有一个.getclass()方法。
和我们理解不一样的是可能是堆内存的结构,在里面并没有存储字段名字,那么jvm是如何准确的引用对象的每一个字段的呢?
以tom.age为例,在执行这段语句时,首先会根据变量名tom找到在栈内存之中,再根据栈内存存储的地址值去找到堆内存中储存的对象,引用age之前会跟随class指针来到方法区找到age的引用规则,offset就是age的引用规则,意思是从起始地址往后移动12位就是age的存放地址,接下来只要往下读4个字节就可以读出age的值来了,需要注意的是name字段在堆内存里存放的还是一个地址值,因为他是一个引用数据类型,也是一个Java对象。
文章灵感来自---【Java必备知识】Java中的对象长什么样?_哔哩哔哩_bilibili
我按照这位老师所讲的添加了一点自己的理解。