Java学习1:图解Java内存分析详解(实例)
首先需要明白以下几点:
- 栈空间(stack),连续的存储空间,遵循后进先出的原则,用于存放局部变量。
- 堆空间(heap),不连续的空间,用于存放new出的对象,或者说是类的实例。
- 方法区(method),方法区在堆空间内,用于存放①类的代码信息;②静态变量和方法;③常量池(字符串敞亮等,具有共享机制)。
- Java中除了基本数据类型,其他的均是引用类型,包括类、数组等等。
- 数据类型的默认值
基本数据类型默认值:
数值型:0
浮点型:0.0
布尔型:false
字符型:\u0000
引用类型:null - 变量初始化
成员变量可不初始化,系统会自动初始化;
局部变量必须由程序员显式初始化,系统不会自动初始化。
实例进行分析。
创建类
分别是Student、Computer、Test,代码如下:
public class Student {
int score;
int age;
String name;
Computer computer;
public void study() {
System.out.println("studying...");
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
public class Computer {
int price;
String brand;
}
- 1
- 2
- 3
- 4
public class Test {
public static void main(String[] args) {
Student stu = new Student();
stu.name = "xiaoming";
stu.age = 10;
stu.study();
Computer c = new Computer();
c.brand = "Hasse";
System.out.println(c.brand);
stu.computer = c;
System.out.println(stu.computer.brand);
// System.out.println("----------------------------------------");
//
// c.brand = "Dell";
//
// System.out.println(c.brand);
// System.out.println(stu.computer.brand);
//
// System.out.println(stu.computer.brand == c.brand);
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
代码分析
我们知道,程序的入口是main(),因而从main方法从上到下、从左到右进行分析。
Student stu = new Student();
①首先,Java虚拟机(JVM)去方法区寻找是否有Test类的代码信息,如果存在,直接调用。如果没有,通过类加载器(ClassLoader)把.class字节码加载到内存中,并把静态变量和方法、常量池加载(“xiaoming”、“Hasse”)。
②走到Student,以同样的逻辑对Student类进行加载;静态成员;常量池(“studying”)。
③走到stu,stu在main方法内部,因而是局部变量,存放在栈空间中。
④走到new Student,new出的对象(实例),存放在堆空间中,以方法区的类信息为模板创建实例。
⑤‘’=‘’赋值操作,把new Student的地址告诉stu变量,stu通过四字节的地址(十六进制),引用该实例。
如下图:
stu.name = “xiaoming”;
⑥stu通过引用new Student实例的name属性,该name属性通过地址指向常量池的"xiaoming"敞亮。
stu.age = 10;
⑦s实例的age属性是基本数据类型,基本数据类型直接赋值。
stu.study();
⑧调用实例的方法时,并不会在实例对象中生成一个新的方法,而是通过地址指向方法区中类信息的方法。
⑥⑦⑧的过程如下图:
Computer c = new Computer();
同stu变量的生成过程。
c.brand = “Hasse”;
同stu.name = "xiaoming"过程。
stu.computer = c;
⑨把c对象对Computer实例的引用赋值给Student实例的computer属性。亦即:该Student实例的computer属性指向该Computer类的实例。
如下图:
拓展
改变brand的地址指向。
为进一步理解,我们把注释内容去掉:
⑨重新将Computer实例的brand属性指向"Dell"常量,那stu.computer.brand指向谁呢?Dell还是Hasse?
c.brand = "Dell";
- 1
根据刚才的分析可知:
stu通过地址引用Student实例,而该实例的computer的指向和c的指向是同一个Computer实例,因而改变该Computer实例的brand属性的指向,两者都会改变。
举个例子:
访问大明,和访问大明的儿子的爸爸,实质上访问的是同一个对象:大明。
因而,最终的结果是true。
理解字符串常量及常量池
下面我们添加新的代码,如下:
String str = "Dell";
System.out.println(c.brand == str);
- 1
- 2
结果会如何呢?
根据常量池具有共享性,可知并不会生成新的常量"Dell",而是会把str通过地址指向原来的"Dell",因而结果是true。
Java学习1:图解Java内存分析详解(实例)的更多相关文章
- Java学习笔记 线程池使用及详解
有点笨,参考了好几篇大佬们写的文章才整理出来的笔记.... 字面意思上解释,线程池就是装有线程的池,我们可以把要执行的多线程交给线程池来处理,和连接池的概念一样,通过维护一定数量的线程池来达到多个线程 ...
- java 堆栈内存分析详解
计算机术语里面堆和栈代表不同的存储结构:stack-栈:heap-堆 所以java虚拟机(JVM)中堆和栈是两种内存 堆.栈对比 对比点 堆 栈 JVM中的功能 内存数据区 内存指令区 动静态 运行时 ...
- 1.4(java学习笔记) 面向对象内存分析
首先介绍几个概念 栈: 1.栈是方法执行的内存模型,每调用一个方法都会创建一个栈帧. 2.jvm为每个线程创建一个栈,存放方法相关信息,栈属于线程私有不共享. 3.栈由系统自动分配,是连续的内存空 ...
- java学习(二)多态中成员变量详解
今天我总结了一下java多态中成员变量的赋值与调用 举一个我当初做过的小案例: class Fu{ int num; void show(){} } class Zi extends Fu{ //in ...
- Java学习之二维数组定义与内存分配详解
二维数组:就是元素为一维数组的一个数组. 格式1: 数据类型[][] 数组名 = new 数据类型[m][n]; m:表示这个二维数组有多少个一维数组. n:表示每一个一维数组的元素有多少个. 注意: ...
- 零拷贝详解 Java NIO学习笔记四(零拷贝详解)
转 https://blog.csdn.net/u013096088/article/details/79122671 Java NIO学习笔记四(零拷贝详解) 2018年01月21日 20:20:5 ...
- java程序运行时内存分配详解
java程序运行时内存分配详解 这篇文章主要介绍了java程序运行时内存分配详解 ,需要的朋友可以参考下 一. 基本概念 每运行一个java程序会产生一个java进程,每个java进程可能包含一个 ...
- Java内存结构详解
Java内存结构详解 Java把内存分成:栈内存,堆内存,方法区,本地方法区和寄存器等. 下面分别介绍栈内存,堆内存,方法区各自一些特性: 1.栈内存 (1)一些基本类型的变量和对象的引用变量都是在函 ...
- 云时代架构阅读笔记六——Java内存模型详解(二)
承接上文:云时代架构阅读笔记五——Java内存模型详解(一) 原子性.可见性.有序性 Java内存模型围绕着并发过程中如何处理原子性.可见性和有序性这三个特征来建立的,来逐个看一下: 1.原子性(At ...
随机推荐
- python编写脚本,登录Github通过指定仓库指定敏感关键字搜索自动化截图生成文件【完美截图】
前言:为了避免开发人员将敏感信息写入文件传到github,所以测试人员需要检查每个仓库是否有写入,人工搜索审核比较繁琐,所以写一个脚本通过配置 配置文件,指定需要搜索的仓库和每个仓库需要搜索的关键字, ...
- 在k8s中收集jvm异常dump文件到OSS
现状 加参数 -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=logs/test.dump 可以实现在jvm发生内存错误后 会生成dump文件 方便开 ...
- 问题 B: 喷水装置(二)(在c++上运行有错误,提交AC了)
题目描述 有一块草坪,横向长w,纵向长为h,在它的橫向中心线上不同位置处装有n(n<=10000)个点状的喷水装置,每个喷水装置i喷水的效果是让以它为中心半径为Ri的圆都被润湿.请在给出的喷水装 ...
- IDEA修改XML注释风格
作为一个强迫症患者,每次想在xml文件用快捷键注释的时候,它自动生成的注释一直都是这样的:这令我非常难受,于是每次我都要把光标移到前面,然后再Tab以下,让它变成这样可是每次都这样,好麻烦啊,如果自己 ...
- 一个没被spring管理的类怎么创建对象并使用里面的方法
一个对象new出来的,如果不是构造器注入@Data 也不好使啊,尝试构造器注入一下,或者set进去 第二次尝试使用这个. 向这种只能构造器注入或者通过上面的set方法来注入了,component是不好 ...
- docker 配置redis并远程访问
我安装的是这个镜像 docker.io/redis docker pull docker mkdir docker cd docker mkdir redis cd redis mkdir data ...
- CF 585 E Present for Vitalik the Philatelist
CF 585 E Present for Vitalik the Philatelist 我们假设 $ f(x) $ 表示与 $ x $ 互质的数的个数,$ s(x) $ 为 gcd 为 $ x $ ...
- 洛谷 P6672 - [清华集训2016] 你的生命已如风中残烛(组合数学)
洛谷题面传送门 题解里一堆密密麻麻的 Raney 引理--蒟蒻表示看不懂,因此决定写一篇题解提供一个像我这样的蒟蒻能理解的思路,或者说,理解方式. 首先我们考虑什么样的牌堆顺序符合条件.显然,在摸牌任 ...
- Codeforces 679E - Bear and Bad Powers of 42(线段树+势能分析)
Codeforces 题目传送门 & 洛谷题目传送门 这个 \(42\) 的条件非常奇怪,不过注意到本题 \(a_i\) 范围的最大值为 \(10^{14}\),而在值域范围内 \(42\) ...
- Atcoder Grand Contest 005 E - Sugigma: The Showdown(思维题)
洛谷题面传送门 & Atcoder 题面传送门 记先手移动棋子的树为红树,后手移动棋子的树为蓝树. 首先考虑一个性质,就是如果与当前红色棋子所在的点相连的边中存在一条边,满足这条边的两个端点在 ...