深入了解 JVM虚拟机

Posted 知物电子

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了深入了解 JVM虚拟机相关的知识,希望对你有一定的参考价值。

JVM是Java程序员的基本功,要好好学习。✊
如有帮助,不胜荣幸。如有错误,欢迎指正!

Java虚拟机内存管理

程序计数器

较小的区域,可以看作当前线程执行的字节码的行号指示器,且每个线程都有自己独立的程序计数器。此区域没有规定内存溢出的情况,因为 我们开发人员不会操作到此区域

Java虚拟机栈

(先进后出)为虚拟机执行Java方法服务,存放栈帧(每个栈帧对应一个方法)。
每个方法执行都会创建栈帧,栈帧中包含局部变量表、返回值地址等信息。栈帧创建好,方法开始执行,待方法执行完 毕,栈帧出栈,随后就会被销毁。
举例:若A方法中调用了B方法,创建A的栈帧,进入栈,开始执行A方法,执行到A调用B的时候,创建B的栈帧,进入栈,开始执行B方法,B方法执行完毕后,B的栈帧出栈,随后被销毁。A方法继续执行余下部分,直至执行完毕,A的栈帧出栈,随后被销毁。
  在使用递归的时候,如果处理不好临界值,很容易就会出现栈内存溢出问题(StackOverFlow)

本地方法栈

为虚拟机执行native方法服务(Native Method就是一个java调用非java代码的接口。一个Native Method是这样一个java的方法:定义被native关键字修饰的接口,该接口的实现由非java语言实现),其他与虚拟机栈完全一致。

Java堆

用于存放对象的实例,是垃圾回收器的主要工作区域,分为 新生代 老年代 ,新生代中又划分Eden区,Survivor1区和Survivor2区,当堆内存不足的时候,就会抛出OutOfMemory异常,我们可以通过-Xms和-Xmx来指定堆内存空间。

方法堆

存储虚拟机加载的类的信息(字段,方法,接口),常量,静态变量以及编译器编译之后的代码。当方法区内存不足的时候,就会抛出OutOfMemory异常。方法区很重要的一部分就是运行时常量池,在类和方法被加载到JVM中,对应的运行时常量池就被创建出来,并非Class文件常量池中的内容才能进入运行时常量池,在运行期间也可将新的常量放入运行时常量池中,比如String的intern方法。

对象

对象的创建

New 类名 → 根据new的参数在常量池中定位一个类的符号引用 → 如果当前常量池中没有这个符号引用,说明这个类还没有被加载,则进行类的加载,解析和初始化 → 虚拟机为对象在堆中分配内存  →  将分配的内存初始化(不包括对象头) → 调用对象的 <init> 方法(构造方法等)

深入了解 JVM虚拟机

对象的结构

Header(对象头)

  • 自身运行时数据(Mark Word)

    • 哈希值

    • GC分代年龄

    • 锁状态标志

    • 线程持有的锁

    • 向线程ID

    • 偏向时间戳

  • 类型指针

InstanceData实例数据

接下来的实例数据部分是对象真正存储的有效信息,也是在程序代码中所定义的各种:类型的字段内容。无论是从父类继承下来的,还是在子类中定义的,都需要记录起来。这部分的存储顺序会受到虚拟机分配策略参数.(FieldsAllocationStyle)和字段在java源码中定:义顺序的影响。在满足这个前提条件的情况下,在父类中定义的变量会由现在子类之前。如果CompactFields 参数值为true(默认为true);那么子类之中较窄的变量也可能会插入到父类变量的空隙之中。

Padding

第三部分对齐填充并不是必然存在的,也没有特别的含义,它仅仅起着占位符的作用。 由HotSpot VM的自动内存管理系统要求对象起始地址必须是8字节的整数倍,换句话说,就是对象的小必须是8字节的整数倍。 而对象买部分正好是8字节的倍数(1倍或者2倍),因此,当对象实例数据部分没有对齐时,就需要通过对齐填充来补全。

往期回顾

更新 |

更新丨

系列文章丨

知物ZhiWu

知物,每天认知新技术

以上是关于深入了解 JVM虚拟机的主要内容,如果未能解决你的问题,请参考以下文章

深入了解JVM——虚拟机类加载机制

深入了解JVM——虚拟机字节码执行引擎

深入了解JVM——虚拟机字节码执行引擎

《深入理解JVM虚拟机》读书笔记

深入了解JVM——虚拟机性能监控与故障处理工具

深入了解JVM——虚拟机性能监控与故障处理工具