1.JVM四大重要组成部分与内存区域

在我去学习JVM之前呢 ,我心里呢存在着下面这些问题:

首先呢,JVM到底是什么??他在那呢??他是怎么实现跨平台性的呢??JDK?JRE?JVM他们都是什么东西呢??他们之间又有什么关系呢??

JDK (Java Development Kit)是针对Java开发员的产品,是整个Java的核心,包括了Java运行环境JRE、Java工具和Java基础类库。

​ JRE(Java Runtime Environment)是运行JAVA程序所必须的环境的集合,包含JVM标准实现及Java核心类库。

​ JVM(Java Virtual Machine),是整个java实现跨平台的最核心的部分,能够运行以Java语言写作的软件程序。

        简单来说就是JDK是Java的开发工具,JRE是Java程序运行所需的环境,JVM是Java虚拟机.它们之间的关系是JDK包含JRE和JVM,JRE包含JVM。

1.JVM的主要组成部分:

JVM的主要组成呢分为四大部分,包含两个子系统和两个组件;

本地库接口: Native Interface:与native lib(本地方法库)交互,融合其他编程语言为Java所用,是与其它编程语言交互的接口

运行时数据区: Runtime data area 即常说的JVM内存;

类加载子系统: Class loader :根据全限定类名,装载class文件到运行时数据区的方法区中。

执行引擎子系统: Execution engine :也叫解释器,负责解释class指令,再提交给操作系统执行

JAVA代码的运行顺序:

j        ava源代码经过编译器生产 字节码文件,由JVM中的类加载器,将字节码文件加载到运行时数据区的方法区中,由于字节码文件并不能被操作系统直接运行,需要通过执行引擎,将字节码文件转化为对应操作系统的系统指令,并交给CPU执行,在该过程中,可能用到其他语言的本地库接口来实现整个程序。

2.JVM内存:

JVM内存呢其实就是,运行时数据区中的内容,其主要包含了五个区域哦:

1.程序计数器:(线程私有)

当前线程执行的字节码行号指示器,记录当前线程执行到那个位置,也可以通过改变计数器的值,来选取下一条需要执行的字节码指令,且是唯一一个不会发生OOM的区域

2.虚拟机栈:(线程私有)

描述java方法执行的内存模型,方法执行时都会创建一个栈帧,每个方法从调用到执行完成,就对应着一个栈帧在虚拟机栈中入栈到出栈的过程。用于存储局部变量表、操作数栈、动态链接、方法出口等信息。生命周期与线程生命周期相同.

3.本地方法栈:(线程私有)

与虚拟机栈类似,描述本地方法的执行内存模型,为本地方法服务.

4.java堆:

用于存放实例化对象的区域,是占用内存最大的区域,分为新生代和老年代,新生代又分为:Eden区域 和 from Survivor区和 to Servivor 区。

在 HotSpot 中,对象在堆内存布局分成三部分:对象头,实例数据,对齐填充。
① 对象头:包括两部分的信息:
运行时数据:存储对象自身的运行数据,如哈希码,GC代年龄,锁状态、线程持有的锁、
偏向线程ID等。
类型指针:即对象指向它的类型数据的指针,虚拟机通过这个指针来确定这个对象是哪个类
的实例。如果对象是一个Java数组,那对象头中还必须有一块用于记录数组长度的数据。
② 实例数据:是对象真正存储的有效信息,是在程序代码中所定义的各种类型的字段内容,
相同宽度的字段会被分配到一起。

③ 对齐填充:并不是必然存在的,仅起着占位符的作用。

5.方法区:

该区域被所有线程共享,用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译后的代码(即class文件)等数据,同时,方法区中有一个运行时常量池,用于存放静态编译产生的字面量和符号引用。该区域不需要连续的内存,并且可以动态扩展,动态扩展失败会抛出 OOM 异常,对该区域进行垃圾回收的主要目标是对常量池的回收和对类型的卸载,但是一般比较难实现。

方法区是一个 JVM 规范,永久代与元空间都是其一种实现方式。JDK8 之前,Hotspot 中方法区的实现是永久代(Perm),JDK8 开始使用元空间(Metaspace),以前永久代的静态变量和常量池移至堆内存,其他内容移至元空间,元空间直接在本地内存分配。

那为什么要使用元空间取代永久代的实现?主要是为了方便管理方法区:

① 永久代与堆所使用的物理内存是连续的。对于永久代,由于类和方法等信息比较难确定大小,所以指定永久代的大小比较困难,太小容易出现永久代溢出,太大则容易导致老年代溢出,并且每次 Full GC 之后永久代的大小都会改变,如果动态生成很多 class 的话,就很可能出现 OOM,毕竟永久代的空间配置有限。

② JDK8之后,方法区存在于元空间,物理内存不再与堆内存连续,而是直接存在于本地内存中,理论上机器内存有多大,元空间就有多大。

③ 字符串存在永久代中,容易出现性能问题和内存溢出。

④ 永久代会为 GC 带来不必要的复杂度,回收效率偏低,因为方法区中类静态属性引用的对象、常量引用的对象都是 GC Roots 对象

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值