《深入理解java虚拟机》读书笔记:java内存区域
来源:互联网 发布:旅行社地接计调软件 编辑:程序博客网 时间:2024/06/05 04:24
书本简介
书名:《深入理解java虚拟机 JVM高级特性与最佳实践》
作者:周志明
版本:第二版
pdf下载链接:csdn下载该电子书
运行时数据区域
关键词:运行时
即在从java虚拟机(JVM)启动到其停止的一段时间内,JVM用来存放必要数据(类信息,对象,常量等等)
画了这么一副图:
程序计数器(Program Counter Register)
与相应线程关联的一个较小的内存空间,用作存放程序下一条指定的位置。属于线程私有的空间,每个线程都需要一个独立的程序计数器。
java虚拟机栈(Java Virtual Machine Stack)
虚拟机栈描述的是 : java方法执行的内存模型(书中原话),我对这句话的理解是:
虚拟机栈,故名思意,它是一个栈结构(先进后出),它里面的元素是一个个的栈桢(Stack Frame),栈桢中存放的是一个方法中的运行必要信息(局部变量表,操作数栈,动态链接,方法出口等)。
想想方法的执行过程:在一个线程中,方法的执行是从上到下执行每一行代码(在虚拟机中是字节码),当遇到一个方法时,将会进入这个方法,执行这个方法的代码,当方法结束时,回到本方法的调用方法的调用点的下一行代码(即程序计数器指向这行代码)。看下面的代码:
public class Test {public static void main(){System.out.println("main:Hello World"); // 1 print(); // 2 // 3}public static void print(){System.out.println("print:Hello World"); //4}}
JVM加载完Test类后,执行main方法。从方法开头向下执行 , 从 1 到 2 ,2 是一个print()方法,进入这个方法执行4,这个方法执行完之后返回到 3 。
在java虚拟机栈中会有两个栈桢进出,分别代表main方法和print方法。
上图,表示了上面示例代码虚拟机栈中栈桢的进出情况。橙色代表栈顶栈桢(正在执行的方法)。
方法区(Method Area)
方法区用于存放已被虚拟机加载的类的类信息,常量,静态变量(类变量)等数据。
运行时常量池(Runtime Constant Pool)
运行时常量池是方法区的一部分,是存放各种字面值常量和符号引用的内存区域。
Java堆
主要用于存放对象实例和数组对象的内存区域。在虚拟机启动时创建(但是书中没有提到,方法区是不是也是这个时候启动,而讲了方法区被实现为“永久代”)
对象的创建
public class Student {
private String name;
private char gender;
public Student(String name,char gender){
this.name = name;
this.gender = gender;
}
}
public class Main{public static void main(String[] args){Student student = new Student("Paul",'m');}}
以上代码创建了一个Student类的实例。但在java虚拟机的内部是怎样的一个过程呢?
使用一个命令将Main中的main方法的字节码(可以看懂的形式,并不是01代码串)得到。
javap -verbose Main
Code: stack=4, locals=2, args_size=1 0: new #2 // class Student 3: dup 4: ldc #3 // String Paul 6: bipush 109 8: invokespecial #4 // Method Student."<init>":(Ljava/lang/String;C)V 11: astore_1 12: return
抓主要矛盾,创建对象实例的关键是new指令(这里的new是java字节码中的new)
- 检查其参数#2(代表常量池中的2号常量,这里是一个类常量,代表Student)在常量池中是否可以找到对应的常量
- 检查该对应类是否已经被加载,解析,初始化过,如果没有则需要先进行这些操作
- 按照对象的大小(在类加载完成后可以确定)从堆中划分出一块内存空间
- 设置对象的一些必要信息(如对象是哪个类的实例,如何找到类的元信息,对象哈希码等信息),这些信息保存在对象的对象头(Object Header)中
- 将新开辟的这块空间(也就是这个对象)的首地址压入操作数栈的栈顶
下面看一看详细每一个字节码都干了什么
字节码 参数 隐含参数 目标 备注 dup 操作数栈顶的一个元素 操作数栈顶将操作数栈顶的元素复制一份再将其压入栈顶(不知道是什么作用) ldc#3 常量池中的第三个常量 操作数栈顶将#3这个常量的值压入栈顶,即常量Paul bipush109 代表字符'm' 操作数栈顶将109压入栈顶 invokespecial#4 常量池中的第四个常量 栈顶的三个元素(这里是三个,对象地址,第一个参数Paul,第二个'm') 操作数栈顶 执行该对象的<init>方法进行初始化,把初始化后的对象地址压入栈中 astore_1 栈顶元素,即已经初始化的对象的地址 局部变量表将栈顶元素保存到本地变量表的Slot 1(理解为第一个空间)中画了个图来帮助理解new指令
图中3 , 4 类加载如果方法区中已经有Student类信息的话会跳过。
对象的内存布局
对象在内存中的存储布局可以分为三个部分:
- 对象头(Header)
- 实例数据(Instance Data)
- 对齐填充(Padding)
对象的访问定位
- 深入理解JAVA虚拟机读书笔记之JAVA内存区域
- 《深入理解Java虚拟机》读书笔记之Java内存区域
- 《深入理解java虚拟机》读书笔记:java内存区域
- 《深入理解java虚拟机》读书笔记一 【java内存区域】
- 《深入理解java虚拟机》读书笔记——jvm内存区域
- 深入理解Java虚拟机--java内存区域
- Java内存区域---深入理解Java虚拟机
- 《深入理解java虚拟机》-java内存区域
- 深入理解java虚拟机-java内存区域
- 深入理解Java虚拟机笔记---内存区域
- 深入理解Java虚拟机笔记---内存区域
- 《深入理解Java虚拟机》读书笔记---第二章 Java内存区域与内存溢出异常
- 《深入理解Java虚拟机》读书笔记1——Java内存区域与内存溢出异常
- 深入理解JAVA虚拟机读书笔记之Java内存区域与内存溢出异常
- 《深入理解Java虚拟机》读书笔记——Java内存区域与内存溢出异常
- 深入理解java虚拟机-读书笔记1-Java内存区域与内存溢出异常
- 《深入理解Java虚拟机》读书笔记:第二章Java内存区域与内存溢出异常
- 《深入理解Java虚拟机》读书笔记:第二章Java内存区域与内存溢出异常
- linux命令之hostname
- CC2530基础实验五 ADC转换实验
- 如何快速定位native方法在对应so中的位置
- 使用skimage.color.rgb2hsv时的一些注意事项
- ValueAnimator的简单介绍和使用
- 《深入理解java虚拟机》读书笔记:java内存区域
- 访问本地环境时出现The requested URL / was not found on this server.
- java——Scanner类
- 不通的页面,点击导航改变背景色--(代码优化后)
- 2017跟着小虎玩着去软考--项目管理师上午考试试题之二(解析2016下半年项目管理师上午试题5-7题)
- 30岁前阅读让你少奋斗十年
- 解压所在目录下所有zip包 ,对解压的文件编辑内容 ,将编辑完的文件存放至目标目录下_02
- java批量删除操作
- 欢迎使用CSDN-markdown编辑器