JVM系列——内存

1、运行时的数据区域

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ebxJBHwS-1646401411431)(C:\Users\崔常菲\AppData\Roaming\Typora\typora-user-images\image-20210911152843017.png)]

程序计数器(Program Counter Register)

线程私有

一块较小的内存空间,看作是当前线程所执行的字节码的行号指示器

字节码解释器工作时就是通过改变这个计数器的值来选取下一条需要执行的字节码指令

若线程正在执行的是一个Java方法, 这个计数器记录的是正在执行的虚拟机字节码指令的地****址; 如果正在执行的是本地(Native) 方法, 这个计数器值则应为(Undefined )

Java虚拟机栈 ( Java Virtual Machine Stack)

线程私有 生命周期与线程相同 为虚拟机执行Java方法(也就是字节码) 服务

每个方法(java方法)被执行的时候, Java虚拟机都会同步创建一个栈帧(Stack Frame) 用于存储局部变量表操作数栈动态连接、 方法出口等信息。

局部变量表存放了编译期可知的各种Java虚拟机基本数据类型

对这个内存区域规定了两类异常状况:

如果线程请求的栈深度大于虚拟机所允许的深度, 将抛出StackOverflowError异常;

如果Java虚拟机栈容量可以动态扩展, 当栈扩展时无法申请到足够的内存会抛出OutOfMemoryError异常

本地方法栈

为虚拟机使用到的本地(Native)方法服务。

HotSpot虚拟机 直接将本地方法栈和虚拟机栈合二为一。

Java堆 (heap)

所有线程共享的一块内存区域, 唯一目的就是存放对象实例 ,Java堆是垃圾收集器管理的内存区域

Java堆既可以被实现成固定大小的, 也可以是可扩展的, 不过当前主流的Java虚拟机都是按照可扩
展来实现的(通过参数**-Xmx**和-Xms设定)

包含新生代老年代,新建的的对象都从新生代分配内存,新生代由Eden Space和两个相同大小的Survivor Space构成。老年代用于存放新生代金国几次垃圾回收仍然存活的对象。

方法区 ( Mehtod Area)

所有线程共享的一块内存区域

用于存储已被虚拟机加载的类型信息、 常量、 静态变量、 即时编译器编译后的代码缓存等数据

运行时常量池 (Runtime Constant Pool)

运行时常量池是方法区的一部分

Class文件中除了有类的版本、 字段、 方法、 接口等描述信息外, 还有一项信息是常量池表(Constant Pool Table) , 用于存放编译期生成的各种字面量与符号引用。

直接内存 (Direct Memory)

不是虚拟机运行时数据区的一部分, 也不是《Java虚拟机规范》 中定义的内存区域。

本机直接内存的分配不会受到Java堆大小的限制, 但是, 既然是内存, 则肯定还是会受到
本机总内存(包括物理内存、 SWAP分区或者分页文件) 大小以及处理器寻址空间的限

2、HotSpot构建对象

对象的创建过程

虚拟机完成以下工作:

①遇到一条new指令的字节码时,检查能否在常量池中定位到一个类的引用,否则先执行类加载

②虚拟机啊分配内存

③初始化内存空间为零值

④对对象进行必要设置。

java程序:调用构造函数,执行方法后,对象正在构造出来

对象内存布局

可以划分为三个部分: 对象头(Header)实例数据(Instance Data和对齐填充(Padding)

对象头部分包括两类信息:

第一类是用于存储对象自身的运行时数据 (哈希码(HashCode) 、 GC分代年龄、 锁状态标志、 线程持有的锁、 偏向线程ID、 偏向时间戳 );

第二类是类型指针, 即对象指向它的类型元数据的指针, Java虚拟机通过这个指针来确定该对象是哪个类的实例 。

实例数据:存储的有效信息

对齐填充:非必然存在,用来对齐补全

对象访问

①句柄访问 (间接访问)reference中存储的直接就是对象地址

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gOPCELZi-1646401411431)(C:\Users\崔常菲\AppData\Roaming\Typora\typora-user-images\image-20210911161932590.png)]

②直接指针访问

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GRoBxacN-1646401411432)(C:\Users\崔常菲\AppData\Roaming\Typora\typora-user-images\image-20210911161941072.png)]

HotSpot使用直接指针访问对象,其主要优势就是速度快

3、java源码编译机制

JVM规范中定义了class文件格式,但未定义java源码如何编译为class文件,各厂商在实现JDK时,通常会讲符合java语言规范的源码编译为class文件的编译器,如javac,其编译步骤如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-m1erQ7uY-1646401411432)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20210921111127461.png)]

分析和输入符号表:

Parse过程所作的为词法和语法的分析,词法分析要完成讲代码字符串变成token序列。语法分析要完成根据token生成抽象语法树

注解处理:

处理用户自定义的annotation,

语义分析和生成class文件:

进行一系列的语义分析

jstat是Java Virtual Machine统计监测工具(Java Virtual Machine Statistics Monitoring Tool)的缩写。它可以用来监测JVM内部的各种运行时数据,包括堆内存、GC情况、类加载器等方面的信息。在调优JVM性能时,jstat是一个非常有用的工具。 使用jstat需要使用命令行,并且需要指定三个参数:监测对象、监测间隔时间和监测次数。下面是一个示例命令: ``` jstat -gcutil 1000 10 ``` 这个命令表示每隔1秒钟(1000毫秒)监测一次GC情况,一共监测10次。其中的“-gcutil”表示要监测的对象是GC情况,可以使用其他参数指定其他的监测对象。 jstat的输出结果包括多列数据,每列数据的含义如下: - S0:第一个幸存区(Survivor)的使用情况。 - S1:第二个幸存区(Survivor)的使用情况。 - E:伊甸园区(Eden)的使用情况。 - O:老年代(Old)的使用情况。 - P:永久代(Permanent)的使用情况。 - YGC:从应用程序启动到采样时发生的Young GC次数。 - YGCT:从应用程序启动到采样时Young GC所用的时间(单位秒)。 - FGC:从应用程序启动到采样时发生的Full GC次数。 - FGCT:从应用程序启动到采样时Full GC所用的时间(单位秒)。 - GCT:从应用程序启动到采样时GC所用的总时间(单位秒)。 除了上述命令外,jstat还可以使用其他参数来监测不同的对象和数据,具体可参考jstat的帮助文档。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值