java 内存分析_【Java】内存分析

栈的特点如下:

1. 栈描述的是方法执行的内存模型。每个方法被调用都会创建一个栈帧(存储局部变量、操作数、方法出口等)

2. JVM为每个线程创建一个栈,用于存放该线程执行方法的信息(实际参数、局部变量等)

3. 栈属于线程私有,不能实现线程间的共享!

4. 栈的存储特性是“先进后出,后进先出”

5. 栈是由系统自动分配,速度快!栈是一个连续的内存空间!

堆的特点如下:

1. 堆用于存储创建好的对象和数组(数组也是对象)

2. JVM只有一个堆,被所有线程共享

3. 堆是一个不连续的内存空间,分配灵活,速度慢!

方法区(又叫静态区)特点如下:

1. JVM只有一个方法区,被所有线程共享!

2. 方法区实际也是堆,只是用于存储类、常量相关的信息!

3. 用来存放程序中永远是不变或唯一的内容。(类信息【Class对象】、静态变量、字符串常量等)

3f43d565e22fa7838fbd09fe15812c8b.png

了解栈、堆和方法区的特点后,我们来对以下代码进行内存分析

public classStudent {//属性(成员变量) field s

intid;

String name;intage;

Computer comp;//方法

voidstudy(){

System.out.println("我在学习");

}voidplay() {

System.out.println("我在玩碧蓝航线!用笔记本"+comp.brand);

}

Student (){//构造方法。用于创建这个类的对象,无参的构造方法可以由系统自动生成

}public static voidmain(String[] args) {

Student stu= new Student();//通过Student类的构造函数Student()方法新建一个stu对象

stu.age=19;

stu.id=19;

stu.name="水音";

Computer c1= newComputer();

c1.brand= "神舟";

stu.comp=c1;

stu.play();

stu.study();

}

}classComputer{

String brand;

}

让我们回到万物的起点

javac Student.java 和 java Student

e5b968a5e24a20432850cbee96cb8be6.png

javac 是将 .java 文件编译成 JVM(java虚拟机)能够读懂的 .class java字节码文件

java 则是执行字节码文件,我们从这里开始分析

在调用 java 的时候,启动虚拟机,内存空间如下图所示

6ab145aea682209b4822f949880652ff.png

接着是执行 Student 类,执行这个类之前需要找到这个类,首先需要把 Student 类加载到内存空间里面

接着在方法区里面,就有了这个类的信息

1d81bf43c974b9d9bf39b51165dc1db5.png

有了这些信息后,相当于 java Student 这条命令执行完了

接着就开始寻找 main 方法,main 方法是程序执行的入口

在调用 main 方法的时候就会在栈中开辟一个栈帧

d7b079cfd5dcf175f22db5f075763d88.png

main 方法

public static voidmain(String[] args) {

Student stu= new Student();//通过Student类的构造函数Student()方法新建一个stu对象

stu.age=19;

stu.id=19;

stu.name="水音";

Computer c1= newComputer();

c1.brand= "神舟";

stu.comp=c1;

stu.play();

stu.study();

}

main 方法首先定义了一个 Student 类型的引用变量 stu ,目前它的值为空(null)

8df566acb824da2afc282c3087918c76.png

接着 new 了一个对象,根据 Student 类的构造器(构造方法)新建,因为调用了方法,所以在栈中开辟一个新的栈帧

f93c34c0d9030d00b5b58630d85cb581.png

开辟完后开始执行这个方法,依据构造器初始化这个类,生成这个类的对象

执行完后获得对象 ,栈帧弹出

注意:这里新建好的对象里面所有属性的值均为默认值

c2a933ba6cb28df987460830a6ceaaa4.png

接着将这个新建好的对象给 stu

也就是把 stu 的地址指向新建好的对象的地址

通过地址值将它们关联起来

Tip:不用在意 1e6d1014这个地址是怎么来的,只是随便打的

9405c5184f839e861affd92007d7b2aa.png

接着执行 stu.age

public static voidmain(String[] args) {

Student stu= new Student();//通过Student类的构造函数Student()方法新建一个stu对象

stu.age=19;

stu.id=19;

stu.name="水音";

Computer c1= newComputer();

c1.brand= "神舟";

stu.comp=c1;

stu.play();

stu.study();

}

在 mian 方法里执行,所以在 main 方法的栈帧里面找 stu 对象,根据 stu 的地址找到 age

并将 age 赋值为 19

6eccc9a2be213ec4d605baa02aee0b45.png

id 的赋值同上

04c2e3dc15f1f96f3a571e493d8f6acd.png

需要注意的是 name 的赋值

找到 name以后,会在方法区里找到 水音这个字符串常量并将 name的地址指向它

https://www.cnblogs.com/syxy/p/9747953.html

接着到了 Computer c1

public static voidmain(String[] args) {

Student stu= new Student();//通过Student类的构造函数Student()方法新建一个stu对象

stu.age=19;

stu.id=19;

stu.name="水音";

Computer c1= newComputer();

c1.brand= "神舟";

stu.comp=c1;

stu.play();

stu.study();

}

在 main新建一个 Computer 类型的局部变量 c1,目前它的值也为 null

3ac4b318b875b408d62a576a93b03833.png

接着执行 new Computer();调用 Computer类的构造方法新建一个对象

classComputer{

String brand;

}

由于没有定义构造方法,所以将按系统按自动生成的默认构造方法来初始化 Computer类

因为调用了方法,所以要在栈中开辟一个新的栈帧

d3942ccfe2a013c49997908f56215c06.png

和前面一样,

开辟完后开始执行这个方法,依据构造器初始化这个类,生成这个类的对象

执行完后获得对象 ,栈帧弹出

再提一遍

注意:这里新建好的对象里面所有属性的值均为默认值

f897b4c014e1b453e0436e4e5b57412a.png

接着将这个新建好的对象给 c1

也就是把 c1 的地址指向新建好的对象的地址

通过地址值将它们关联起来

1530c6d4857639de454eaeb4033551b7.png

接着执行 c1.brand

public static voidmain(String[] args) {

Student stu= new Student();//通过Student类的构造函数Student()方法新建一个stu对象

stu.age=19;

stu.id=19;

stu.name="水音";

Computer c1= newComputer();

c1.brand= "神舟";

stu.comp=c1;

stu.play();

stu.study();

}

在 mian 方法里执行,所以在 main 方法的栈帧里面找 c1 对象,根据 c1 的地址找到 brand

找到 brand以后,会在方法区里找到 神舟这个字符串常量并将 brand的地址指向它

15198e82561dbf9ce494f1ab0141b4a1.png

接着执行 stu.comp,在 stu 中找到 comp

将 c1赋值给 comp,就是将 comp 的地址指向 c1

相当于 comp也是指向614ddd49

14823124aef76411bb84bf0e696a232e.png

接着执行 stu.play,在 stu 中找到 play方法

为 play方法在栈中创建一个栈帧

public classStudent {//属性(成员变量) field s

intid;

String name;intage;

Computer comp;//方法

voidstudy(){

System.out.println("我在学习");

}voidplay() {

System.out.println("我在玩碧蓝航线!用笔记本"+comp.brand);

}

Student (){//构造方法。用于创建这个类的对象,无参的构造方法可以由系统自动生成

}public static voidmain(String[] args) {

Student stu= new Student();//通过Student类的构造函数Student()方法新建一个stu对象

stu.age=19;

stu.id=19;

stu.name="水音";

Computer c1= newComputer();

System.out.println(c1);

c1.brand= "神舟";

stu.comp=c1;

stu.play();

stu.study();

}

}

其他的由于也没讲到,所以就不写下去了,仅为学面向对象抛砖引玉之用

如有错误,多谢指正

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值