【JVM】介绍、内存概念模型、类加载机制

15 篇文章 0 订阅

一、概述

虚拟机是一种抽象化的计算机,通过在实际的计算机上仿真模拟各种计算机功能来实现的。Java虚拟机有自己完善的硬体架构,如处理器、堆栈、寄存器等,还具有相应的指令系统。Java虚拟机屏蔽了与具体操作系统平台相关的信息,使得Java程序只需生成在Java虚拟机上运行的目标代码(字节码),就可以在多种平台上不加修改地运行。

得益于Java虚拟机,Java自诞生起便提出口号“Write Once, Run Anywhere”

程序、虚拟机、操作系统关系图

JDK、JRE 区别:

  • JDK 指整个Java技术体系
  • JRE 指支持Java程序运行的标准环境

Java技术体系:

  • Java程序设计语言
  • 各种硬件平台上的Java虚拟机
  • Class文件格式
  • Java API 类库
  • 第三方 Java 类库

常见虚拟机

虚拟机特点
Sun Classic/Exact VM
HotSpot VMJava默认虚拟机,以热点探测技术而命名,热点探测能通过执行计数器找出最具编译价值的代码,并以方法为单位进行编译。
BEA JRocketJRocket虚拟机以垃圾收集器、Java Mission Control故障处理套件功能而闻名于世,现已不再发展
IBM J9一款由IBM设计,可在服务端、桌面应用、嵌入式得到全方位应用的虚拟机。其闻名于优秀的职责分离、模块化。
BEA Liquid一款不需要操作系统支持的虚拟机,它自身实现了一个专用的操作系统功能(线程调度、文件系统、网络支持),线程切换无需进行内核态/用户态切换。
Azul VM运行于Vega系统上的虚拟机,每个实例可管理至少数十个CPU、数百GB内存,因其可在巨大内存范围内可控的垃圾收集器(PGC和C4)闻名

使用java -version查看当前ava版本号、虚拟机
查看当前虚拟机

Graal VM

Graal VM 虚拟机的口号:“Run Program Faster Anywhere”

GraalVM ,一个高性能的通用虚拟机,可以运行使用 JavaScript,Python 3,Ruby,R,基于 JVM 的语言以及基于 LLVM 的语言开发的应用。 GraalVM 消除了编程语言之间的隔离性,并且通过共享运行时增强了他们的互操作性。它可以独立运行,也可以运行在 OpenJDK,Node.js,Oracle,MySQL 等环境中。

Graal VM(Unique VM, Polyglot VM)在HotSopt虚拟机基础上增强而成的跨语言全栈虚拟机,可以作为“任何语言”的运行平台 (支持Java、Scala、Groovy、Kotlin等基于Java虚拟机的语言,C、C++、Rust等基于LLVM的语言,JavaScript、Ruby、Python、R等语言),Graal VM 可以无额外开销的混合使用它们。
Graal VM

其基本工作原理是将语言源代码 / 编译后的中间格式转化为能被Graal VM 接受的中介格式,这个过程称为 程序特化 (Specialized, Partial Evaluation)。它提供Truffle工具集以便快速构建Sulong高性能LLVM字节码解释器。

二、内存概念模型

JVM 内存概念模型,用以表示 运行时数据区域(Runtime Data Areas)
运行时数据区域

1、程序计数器

程序计数器 (Program Counter Register) 是一块很小的内存空间,它可以看作当前线程执行字节码的行号指示器,它控制分支循环跳转异常处理线程恢复

2、Java 虚拟机栈

Java 虚拟机栈(JVM Stack)为虚拟机执行 Java方法 (字节码) 服务。它是线程私有的,生命周期与线程相同。

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

局部变量表存放了基本数据类型、对象引用类型,它不等同于对象本身,而是一个指向对象起始地址的引用指针。

当线程请求栈深度大于允许深度时,抛出StackOverFlowError异常;栈扩展失败时,抛出OutOfMemoryError异常。

3、本地方法栈

本地方法栈 (Native Method Stacks) 为虚拟机使用本地 (Native)方法服务。在如Hot-Spot等虚拟机中,将 虚拟机栈 与 本地方法栈 合二为一。

当本地方法栈深度溢出时,抛出StackOverFlowError异常;栈扩展失败时,抛出OutOfMemoryError异常。

4、Java 堆

Java堆 (Java Heap) 是虚拟机管理最大的一块内存,它被各线程所共享,在虚拟机启动时创建。Java 几乎所有的对象实例、数组都分配在堆空间。

Java堆是垃圾收集器管理的内存区域,也被称为GC堆。当堆无法再申请到内存时会抛出OutOfMemoryError异常。

5、方法区

方法区 (Method Area) 与Java 堆一样,被各个线程所共享,用以存储类型信息变量静态变量即时编译的代码缓存等。它逻辑上属于堆,但实际上为了与堆空间作用不同,为了区分它们,方法区还有一个别名——非堆 (Non-Heap)。

当方法区无法再申请到内存时会抛出OutOfMemoryError异常。

6、运行时常量池

运行时常量池 (Runtime Constant Pool) 是方法区的一部分。Class文件中有版本字段方法接口,还有 常量池表 (Constant Pool Table) 以存放编译期间生成的各种字面量、符号引用,在类加载后会放入方法去的方法区的运行时常量池中。

当常量池无法再申请到内存时会抛出OutOfMemoryError异常。

7、直接内存

直接内存(Direct Memory)并不是虚拟机运行时数据区的一部分,但是这部分内存被频繁使用。这部分区域也可能抛出OutOfMemoryError异常。

在JDK1.4中新加入了 NIO (New Input/Output)类,引入了基于通道 (Channel)、缓冲区 (Buffer) 的 I/O 方式。它通过使用 Native 函数库直接分配堆外内存,通过一个存储在Java堆里的DirectByteBuffer对象对这块内存引用进行操作,可以提高性能。

三、类加载机制

1、类加载的时机

  • 隐式加载 new 创建类的实例,
  • 显式加载:loaderClass,forName等
  • 访问类的静态变量,或者为静态变量赋值
  • 调用类的静态方法
  • 使用反射方式创建某个类或者接口对象的Class对象。
  • 初始化某个类的子类
  • 直接使用java命令来运行某个主类

2、类的生命周期

加载:
加载字节码文件(.class)

链接:
确保 Class 文件的字节流中包含的信息符合当前虚拟机的要求,并且不会危害虚拟机自身的安全。为类的静态变量分配内存并设为jvm默认的初值,对于非静态的变量,则不会为它们分配内存。将常量池中的符号引用转换为直接引用。

初始化:
执行类中定义的 Java 程序代码,此阶段是执行 () 方法的过程

使用:
使用阶段包括主动引用和被动引用,主动饮用会引起类的初始化,而被动引用不会引起类的初始化。
卸载:
满足一定条件后,JVM卸载类(在方法区中清空类信息),生命周期结束。

3、双亲委托机制

双亲委派模式:要求除顶层的启动类加载器(bootstrap),其余的类加载器都应该有自己的父类加载器,但是在双亲委派模式中父子关系采取的并不是继承的关系,而是采用组合关系来复用父类加载器的相关代码。

4、三大加载器

bootstrap

  • 加载 jre/lib/下面的核心类库

extension

  • 加载jre/lib/ext下的类库

application

  • 加载用户类 classpath变量定义的目录
    类加载器
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值