说来惭愧,之前一直没有写过博客,学习的内容或者一些技术类话题也只是记录在云笔记上,今天偶然间想起来这件事情,从今天开始不定时更新博客,如有不正确或者待讨论的地方欢迎看到的朋友评论。
技术分享从学习周志明的《深入理解java虚拟机》开始吧。文章内容为本人读书笔记,如有雷同,那我们真是太有缘了。
下面进入正文:
=================================================================
JVM中运行时数据区:方法区、虚拟机栈、本地方法栈、堆、程序计数器
1.程序计数器:
(1)较小的内存空间,相当于当前线程执行字节码的行号指示器,字节码解释器工作时就是通过改变该计数器的值来执行下一条需要执行的字节码指令(分支、循环、跳转、异常处理、恢复线程)。
(2)在一个确定的时刻,一个核只处理一条线程中的指令,为了线程切换后可以恢复到正确的位置,因此每个线程都有一个独立的程序计数器,互不影响,独立存储,这类内存区域称为线程私有内存。
(3)若线程执行的是java方法,则计数器记录的是当前执行的字节码地址,若执行的是native方法,则计数器为空(undefined),此内存区域是java规范中唯一没有规定oom情形的区域。
2.java虚拟机栈:
(1)线程私有内存,其生命周期与线程相同;虚拟机栈描述java方法执行的内存模型:每个方法执行的同时,会创建一个栈帧,用于存储局部变量表、操作数栈、动态链接、方法出口等信息。方法执行的过程就对应栈帧从入栈到出栈的过程。
(2)局部变量表存放了编译期间可知的各种基本数据类型(boolean,byte,char,short,int,long,float,double),对象的引用(reference类型)和returnAddress类型(指向了一条字节码指令的地址);其中long和double占用两个局部变量空间(slot),其余均为一个。
(3)规定两种异常情形:1.如果线程请求的栈深度大于栈允许的深度,报stack over flow;2.如果虚拟机在扩展栈时无法申请到足够的内存,报oom异常。
3.本地方法栈:
(1)与虚拟机栈非常类似,他们之间的区别在于本地方法栈为native方法服务;与虚拟机栈一样,也会抛出out of memory和stack over flow的异常。
4.java堆:
(1)一般来说,java堆是虚拟机中最大的一块内存,是线程共享的,在虚拟机启动的时候创建,唯一的目的就是存放对象实例(几乎所有的对象实例)。
(2)是垃圾回收的主要区域,只需要逻辑连续即可,当堆无法扩展时,抛出out of memory。
5.方法区:
(1)是各线程共享的内存区域,用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。
(2)只需要逻辑内存连续即可,可以选择固定大小也可以选择扩展,还可以选择不进行垃圾回收。当方法区无法满足内存分配需求时,将抛出oom。
(3)其中包括运行时常量池:存放编译器生成的各种字面量和符号引用。
6.直接内存:
(1)并不是虚拟机运行时的数据区域,也不是java虚拟机规范中的内存区域。但是这部分内存也被频繁使用,也可能出现oom异常。
(2)在jdk1.4引入了基于通道与缓冲区的I/O方式,可以使用native函数直接分配堆外内存。通过在java堆中的DirectByteBuffer对象作为这块内存的引用进行操作。
HotSpoot虚拟机对象探秘:对象的创建、对象的内存访问、对象的访问定位
1.对象的创建:
(1)遇到new指令,首先检查这个指令的参数是否能在常量池中定位到一个类的符号引用,并检查这个类的符号引用代表的类是否已被加载、解析和初始化过。如果没有限制性类还在过程。
(2)为新生对象分配内存,对象所需要的内存大小在类加载后已经可以确定。
(3)执行完上述步骤,在虚拟机的角度已经产生了一个新对象了,从java程序来看,还需要初始化对象,因此在new指令执行后一般还需要执行<init>方法,这样一个对象才完全生产出来。
2.对象的内存访问:
(1)对象在内存中存储氛围3块区域:对象头(Header)、实例数据(InstanceData)和对齐填充(padding)。
(2)对象头包括两部分信息:对象自身运行时数据、类型指针。
(3)对象自身运行时数据:哈希码、GC分代年龄、锁状态标志、线程持有的锁、偏向线程ID、偏向时间戳等。
(4)类型指针:对象指向它的类元数据的指针,虚拟机通过这个指针来确定这个对象是那个类的实例。如果对象是数组,那么对象头中还有一个数据用于记录数组的长度。
3.对象的访问定位:
(1)java程序通过reference数据来操作堆上的具体对象。目前主流的访问方式有使用句柄和直接指针两种。
(2)使用句柄的方式:java堆中划出一块内存作为句柄池,reference对象中存放的是句柄的地址,句柄中包含了对象实例数据与类型数据各自具体的地址。
(3)直接指针访问:reference中存的直接就是对象的地址,而对象类型数据的指针则存放在对象中。
小结一下:JVM运行时内存分为:程序计数器、java堆、方法区、java虚拟机栈、本地方法栈;其中程序计数器是线程私有内存;其他线程私有内存的还有java虚拟机栈、本地方法栈。程序计数器,相当于程序执行的指针,记录程序执行到哪一行,以及确定下一条指令的内容;虚拟机栈存放一些局部变量、操作数栈、动态链接及方法出口信息等,本地方法栈就是与虚拟机栈类似,存放native方法的相关内容;java堆和方法区都是线程共享的内存区域,java堆就是存放对象的实例,几乎所有new出来的对象都是存放在这个区域的。方法区则存储已被虚拟机加载的类信息,常量信息及静态变量。
分享到:
相关推荐
### 第二章:数组 - **定义**:一组有序元素的集合。 - **初始化**:创建数组并为元素赋值。 - **访问**:通过索引访问数组元素。 - **遍历**:使用循环结构遍历数组。 ### 第三章:面向对象程序开发 - **封装**:...
#### 第二章:标识符、关键字和数据类型 - **1.8 标识符和关键字** - **标识符**:用于命名变量、方法、类等的名称。 - **关键字**:Java语言中具有特定含义的单词。 - **1.9 Java语言基本数据类型** Java的...
#### 第二章:基础语法 **一、关键字** Java中有53个关键字,如`public`、`private`、`protected`、`static`、`final`等,用于声明类、变量、方法等。 **二、标识符** 1. **命名规则**: - 由字母、数字、...
Java作为一种跨平台的高级编程语言,其核心机制之一就是**Java虚拟机(JVM)**,它解决了传统编程语言的平台依赖性问题,并引入了垃圾回收机制,使得程序员无需手动管理内存,大大提升了开发效率和程序的安全性。...
### 第二章:数组 - 数组是一种固定长度的数据结构,用于存储同类型元素。 - 支持一维数组、二维数组等多维数组。 - 数组操作包括声明、初始化、访问和遍历等。 ### 第三章:面向对象程序开发 - **封装**:隐藏...
#### 第二章:数组 - **数组定义**:数组是Java中用来存储固定数量的同类型元素的容器。数组的元素可以通过索引访问,索引从0开始。 - **数组初始化**:数组可以通过显式初始化或动态初始化的方式创建。显式初始化...
5. **自动垃圾回收**:Java拥有自动内存管理功能,通过垃圾回收机制自动清理不再使用的对象,从而避免了手动管理内存可能导致的内存泄漏等问题。 6. **跨平台性**:Java的一个重要特性就是“编写一次,到处运行”...
#### 第二章 数组 - 数组是用于存储固定大小的同类型元素的数据结构。 - 数组支持索引访问,可以快速定位到特定元素。 - Java中的数组通过索引访问,索引从0开始。 #### 第三章 面向对象程序开发 - 面向对象编程...
第二章涉及的是Java程序的编写和执行: 1. 当一个Java源文件中包含正确的主类(含有`public static void main(String[] args)`方法)时,如示例1所示,执行将显示"Hello World"(问题1,答案A)。 2. 如果主类名与...
**第二章:Java语法** 2.1 关键字与标识符 关键字在Java中具有特殊含义,不能作为变量或类名。标识符则用于命名类、变量和方法,遵循特定的命名规则。 2.2 注释 注释在代码中用于解释和说明,包括单行注释、多行...