菜鸟学Java(二十三)——Java内存分析
我们常说的Java内存主要分为四大块(寄存器不在考虑之内,我们无法用代码来操控它):stack(栈)、heap(堆)、data segment(数据区)、code segment(代码区)。它们的主要用途如下图所示:
而在上面四个当中,我们经常谈论的是右边那两个家伙——stack和heap。今天我们就来聊聊Java代码在运行的过程中,在stack和heap中到底是什么样子的吧。
我们先看下面一段代码:
public static void main(String[] args) {
TestReference testReference = new TestReference();
int age = 1;
Person xiaoqiang = new Person("小强", 21);
Person xiaoming = new Person("小明", 22);
testReference.selfPlus(age);
System.out.println("age经过selfPlus方法的处理后为:" + age);
testReference.changeName(xiaoqiang);
System.out.println("小强经过changeName方法的处理后的名字为:" + xiaoqiang.getName());
testReference.changeAge(xiaoming);
System.out.println("小明经过changeAge方法的处理后的年龄为:" + xiaoming.getAge());
}
public void selfPlus(int i) {
i = i + 1;
}
public void changeName(Person person) {
person = new Person("小刚");
}
public void changeAge(Person person) {
person.setAge(25);
}
执行完以上代码,会打印出什么内容呢?如果你Java基础还可以,那么很容易就能知道会输出什么内容,想要知道以上代码会打印什么内容,需要你明白Java代码在stack和heap中是怎么工作的。下面我们结合几张图来看看:
int i = 1;
Person xiaoqiang = new Person("小强", 21);
Person xiaoming = new Person("小明", 22);
当我们执行完上面三行代码时,内存中的情况如下图所示:
我们知道stack是用来存放变量的,所以age、xiaoqiang和xiaoming三个变量会被存放到stack里,而age又是int类型,所以它的值也会被存放在stack里面。xiaoqiang和xiaoming为Person类型的引用变量,所以stack只会存放它们的一个引用,也就是对应对象的内存地址,而它们真正的内容被存放在了heap里面。
当执行到testReference.selfPlus(i);时,selfPlus(int i)方法被调用,此时会在stack中为形参I开辟一块内存空间,并将其值设置为1,此时内存中的情况如下:
因为调用selfPlus(int i)方法时,将age作为形参传递给该方法,相当于将age的值复制一份给i,所以现在i的值为1,接着执行i = i + 1;此时i的值被修改为2,如图:
此时被修改的只是age的副本,而并非age本身,所以age仍为1,当selfPlus(int i)方法被执行完,i被销毁,age不变。接下来看xiaoqiang,当调用changeName(Person person)方法时,会在stack中为person分配一块空间,里面存放的是xiaoqiang指向的地址,如图:
然后执行到person = new Person("小刚");时,由于又new了一个Person对象,所以在堆中会新建一个person,姓名叫小刚,并且会将person执行小刚的地址,如图:
此时,person指向的对象由小强变成了小刚,但是xiaoqiang所指向的对象仍然是小强,并没有发生任何变化。当changeName方法执行完以后,person被销毁,而小刚也会因为没有任何对象对其进行引用,随后被垃圾回收器回收掉。
下面到了最后一个方法了,当执行testReference.changeAge(xiaoming);时,调用changeAge(Person person)方法,同样会在stack中为person分配一块空间,这次里面存放的是xiaoming对应的内存地址,如图:
然后执行person.setAge(25);,此时person指向的对象为小明,所以在执行setAge方法时,修改的就是heap中小明的属性值,此时小明的年龄被修改为25,。方法执行完毕,person被销毁,内存中最终结果如下:
内存中的最终情况就如上图所示,当然当main方法执行完以后,之前创建的所有对象都会被销毁。OK,每天上班做项目的你是不是把一些基础的东西忘了呢?如果是的话就赶快来补一补吧,好处还是很多的。
菜鸟学Java(二十三)——Java内存分析的更多相关文章
- Java运行原理及内存分析
Java运行原理及内存分析 一.Java运行原理 二.Java内存分析
- Eclipse中的快捷键快速生成常用代码(例如无参、带参构造,set、get方法),以及Java中重要的内存分析(栈、堆、方法区、常量池)
(一)Eclipse中的快捷键: ctrl+shift+f自动整理选择的java代码 alt+/ 生成无参构造器或者提升信息 alt+shift+s+o 生成带参构造 ctrl+shift+o快速导 ...
- Java面向对象_对象内存分析—值传递和引用传递
对象内存分析,我一直学的比较模糊,今天抽空整理一下,希望能理清. 先说一下,内存分析从何而来,这对于我们这些刚接触java的人来说都比较模糊,就从new关键字说起吧. new关键字表示创建一个对象或者 ...
- 巩固java(二)----JVM堆内存结构及垃圾回收机制
前言: 我们在运行程序时,有时会碰到内存溢出(OutOfMemoryError)的问题,为了解决这种问题,我们有必要了解JVM的内存结构和垃圾回收机制. 正文: 1.JVM堆内存结构 ...
- Java数组(基本+内存分析)
一.数组概念 数组即为多个相同数据类型数据的数据按一定顺序排列的集合. 二.数组的特点 1.数组有数组名.索引.元素.素组长度: 2.数组的元素可以是基本数据类型也可以是引用数据类型: ...
- Java的引用类型的内存分析
一. jdk的内存:jdk的bin目录常见命令 1. javac.exe:编译java源代码的,生成java字节码文件(*.class) 2. java.exe:启动一个jvm,来运行指定class字 ...
- java基础知识回顾之---java String final类 容易混淆的java String常量池内存分析
/** * 栈(Stack) :存放基本类型的变量数据和对象的引用,但对象本身不存放在栈中,而是存放在堆(new 出来的对象)或者常量池中(字符串常量对象存放 在常量池中). 堆(heap):存 ...
- Java基础学习笔记二十三 Java核心语法之反射
类加载器 类的加载 当程序要使用某个类时,如果该类还未被加载到内存中,则系统会通过加载,链接,初始化三步来实现对这个类进行初始化. 加载就是指将class文件读入内存,并为之创建一个Class对象.任 ...
- java构造器级简单内存分析
java构造器的使用(基础篇) 构造方法也叫构造器,是创建对象时执行的特殊方法,一般用于初始化新对象的属性. 基本定义语法: 访问控制符 构造方法名([参数列表]){ 方法体 } 注:"访问 ...
- Java进阶(二十三)java中long类型转换为int类型
java中long类型转换为int类型 由int类型转换为long类型是向上转换,可以直接进行隐式转换,但由long类型转换为int类型是向下转换,可能会出现数据溢出情况: 主要以下几种转换方法,供参 ...
随机推荐
- OSX 10.13 以后实现终端FTP命令(转)
macOS10.13 以后就没了........ 这样操作亲测可以恢复 1,brew install telnet 2,brew install inetutils 3,brew link --ove ...
- HDU 1542 矩形面积并【离散化+线段树+扫描线】
<题目链接> 题目大意: 给你n个矩形,求出它们面积的并. 解题分析: 此题主要用到了扫描线的思想,现将各个矩形的横坐标离散化,然后用它们离散化后的横坐标(相当于将矩形的每条竖线投影在x轴 ...
- 计蒜客-跳跃游戏二 (简单dp)
题目链接:https://nanti.jisuanke.com/t/20 跳跃游戏二 给定一个非负整数数组,假定你的初始 ...
- 三篇文章带你极速入门php(二)之迅速搭建php环境
前言 今天讲一下php在windows,mac,linux上的集成环境搭建,目标是简单快速,环境这个事得对号入座,windows用phpstudy,mac用mamp,linux用lnmp一键安装,直接 ...
- 为什么要使用getter/setter
变量私有化的好处 1. 在setter中可以加入合法性检查,比如设置颜色的函数中,对于RGB颜色要判断其值在0~255之间. 2. 更新与被设置变量相关的其它变量的值,比如在一个潜水艇模拟系统中,改变 ...
- Shell function
function test() { echo $1 echo $2 echo $3 } test 1 2 4 在shell里面使用函数是不用括号的.参数直接接在名字后面.
- 潭州课堂25班:Ph201805201 第十四课 异常,处理 (课堂笔记)
程序难免会出现错误 : 语法错误 : 逻辑错误: AttributeError -->> 试图访问一个对象没有的属性, IOError ---->> 输入输出异常 In ...
- rabbitmq使用(三)
Publish/Subscribe In the previous tutorial we created a work queue. The assumption behind a work que ...
- JVM加载class文件的原理机制(转)
JVM加载class文件的原理机制 1.Java中的所有类,必须被装载到jvm中才能运行,这个装载工作是由jvm中的类装载器完成的,类装载器所做的工作实质是把类文件从硬盘读取到内存中 2.java中的 ...
- String、StringBuffer、StringBulider
三者都实现了CharSequence接口,因此CharSequence可认为是一个字符串的协议接口 1.String类是不可变类,即一旦一个String对象被创建后,包含在这个对象中的字符序列是不可改 ...