iis服务器助手广告
返回顶部
首页 > 资讯 > 精选 >如何深度解析JVM
  • 760
分享到

如何深度解析JVM

2023-06-17 12:06:11 760人浏览 八月长安
摘要

如何深度解析JVM,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。首先这里澄清两个概念:JVM实例和JVM执行引擎实例,JVM实例对应了一个独立运行的Java程序,而JVM执行引

如何深度解析JVM,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。

首先这里澄清两个概念:JVM实例和JVM执行引擎实例,JVM实例对应了一个独立运行的Java程序,而JVM执行引擎实例则对应了属于用户运行程序的线程;也就是JVM实例是进程级别,而执行引擎是线程级别的。

JVM是什么?—JVM的生命周期

JVM实例的诞生:当启动一个Java程序时,一个JVM实例就产生了,任何一个拥有publicstaticvoidmain(String[]args)函数的class都可以作为JVM实例运行的起点,既然如此,那么JVM如何知道是运行classA的main而不是运行classB的main呢?这就需要显式的告诉JVM类名,也就是我们平时运行Java程序命令的由来,如JavaclassAhelloworld,这里Java是告诉os运行SunJava2SDK的Java虚拟机,而classA则指出了运行JVM所需要的类名。

JVM实例的运行:main()作为该程序初始线程的起点,任何其他线程均由该线程启动。JVM内部有两种线程:守护线程和非守护线程,main()属于非守护线程,守护线程通常由JVM自己使用,Java程序也可以标明自己创建的线程是守护线程。JVM实例的消亡:当程序中的所有非守护线程都终止时,JVM才退出;若安全管理器允许,程序也可以使用Runtime类或者System.exit()来退出。

JVM是什么?—JVM的体系结构

粗略分来,JVM的内部体系结构分为三部分,分别是:类装载器(ClassLoader)子系统,运行时数据区,和执行引擎。下面将先介绍类装载器,然后是执行引擎,***是运行时数据区

类装载器,顾名思义,就是用来装载.class文件的。JVM的两种类装载器包括:启动类装载器和用户自定义类装载器,启动类装载器是JVM实现的一部分,用户自定义类装载器则是Java程序的一部分,必须是ClassLoader类的子类。(下面所述情况是针对Sunjdk1.2)

动类装载器:只在系统类(Javaapi的类文件)的安装路径查找要装入的类

用户自定义类装载器:

系统类装载器:在JVM启动时创建,用来在CLASSPATH目录下查找要装入的类其他用户自定义类装载器:这里有必要先说一下ClassLoader类的几个方法,了解它们对于了解自定义类装载器如何装载.class文件至关重要。

protectedfinalClassdefineClass(Stringname,bytedata[],intoffset,intlength) protectedfinalClassdefineClass(Stringname,bytedata[],intoffset,intlength,ProtectionDomainprotectionDomain);protectedfinalClassfindSystemClass(Stringname) protectedfinalvoidresolveClass(Classc)

defineClass用来将二进制class文件(新类型)导入到方法区,也就是这里指的类是用户自定义的类(也就是负责装载类)

findSystemClass通过类型的全限定名,先通过系统类装载器或者启动类装载器来装载,并返回Class对象。

ResolveClass:让类装载器进行连接动作(包括验证,分配内存初始化,将类型中的符号引用解析为直接引用),这里涉及到Java命名空间的问题,JVM保证被一个类装载器装载的类所引用的所有类都被这个类装载器装载,同一个类装载器装载的类之间可以相互访问,但是不同类装载器装载的类看不见对方,从而实现了有效的屏蔽。

执行引擎:它或者在执行字节码,或者执行本地方法

要说执行引擎,就不得不的指令集,每一条指令包含一个单字节的操作码,后面跟0个或者多个操作数。

(一)指令集以栈为设计中心,而非以寄存器为中心这种指令集设计如何满足Java体系的要求:

平台无关性:以栈为中心使得在只有很少reGISter的机器上实现Java更便利compiler一般采用stack向连接优化器传递编译的中间结果,若指令集以stack为基础,则有利于运行时进行的优化工作与执行即时编译或者自适应优化的执行引擎结合,通俗的说就是使编译和运行用的数据结构统一,更有利于优化的开展。

网络移动性:class文件的紧凑性。

安全性:指令集中绝大部分操作码都指明了操作的类型。(在装载的时候使用数据流分析期进行一次性验证,而非在执行每条指令的时候进行验证,有利于提高执行速度)。

(二)执行技术

主要的执行技术有:解释,即时编译,自适应优化、芯片级直接执行其中解释属于***代JVM,即时编译JIT属于第二代JVM,自适应优化(目前Sun的HotspotJVM采用这种技术)则吸取***代JVM和第二代JVM的经验,采用两者结合的方式

自适应优化:开始对所有的代码都采取解释执行的方式,并监视代码执行情况,然后对那些经常调用的方法启动一个后台线程,将其编译为本地代码,并进行仔细优化。若方法不再频繁使用,则取消编译过的代码,仍对其进行解释执行。

运行时数据区:主要包括:方法区,堆,Java栈,PC寄存器,本地方法栈

(1)方法区和堆由所有线程共享

堆:存放所有程序在运行时创建的对象

方法区:当JVM的类装载器加载.class文件,并进行解析,把解析的类型信息放入方法区。

(2)Java栈和PC寄存器由线程独享,在新线程创建时间里

(3)本地方法栈:存储本地方法调用的状态

上边总体介绍了运行时数据区的主要内容,下边进行详细介绍,要介绍数据区,就不得不说明JVM中的数据类型。

JVM中的数据类型:JVM中基本的数据单元是Word,而word的长度由JVM具体的实现者来决定

数据类型包括基本类型和引用类型,

(1)基本类型包括:数值类型(包括除boolean外的所有的Java基本数据类型),boolean(在JVM中使用int来表示,0表示false,其他int值均表示true)和returnAddress(JVM的内部类型,用来实现finally子句)。

(2)引用类型包括:数组类型,类类型,接口类型

前边讲述了JVM中数据的表示,下面让我们输入到JVM的数据区

首先来看方法区:

上边已经提到,方法区主要用来存储JVM从class文件中提取的类型信息,那么类型信息是如何存储的呢?众所周知,Java使用的是大端序(big?endian:即低字节的数据存储在高位内存上,如对于1234,12是高位数据,34为低位数据,则Java中的存储格式应该为12存在内存的低地址,34存在内存的高地址,x86中的存储格式与之相反)来存储数据,这实际上是在class文件中数据的存储格式,但是当数据倒入到方法区中时,JVM可以以任何方式来存储它。

类型信息:包括class的全限定名,class的直接父类,类类型还是接口类型,类的修饰符(public,等),所有直接父接口的列表,Class对象提供了访问这些信息的窗口(可通过Class.forName(“”)或instance.getClass()获得),下面是Class的方法,相信大家看了会恍然大悟,(原来如此J)

getName(),getSuperClass(),isInterface(),getInterfaces(),getClassLoader();

static变量作为类型信息的一部分保存

指向ClassLoader类的引用:在动态连接时装载该类中引用的其他类

指向Class类的引用:必然的,上边已述

该类型的常量池:包括直接常量(String,integer和floatpoint常量)以及对其他类型、字段和方法的符号引用(注意:这里的常量池并不是普通意义上的存储常量的地方,这些符号引用可能是我们在编程中所接触到的变量),由于这些符号引用,使得常量池成为Java程序动态连接中至关重要的部分

字段信息:普通意义上的类型中声明的字段

方法信息:类型中各个方法的信息

编译期常量:指用final声明或者用编译时已知的值初始化的类变量

class将所有的常量复制至其常量池或者其字节码流中。

方法表:一个数组,包括所有它的实例可能调用的实例方法的直接引用(包括从父类中继承来的)

除此之外,若某个类不是抽象和本地的,还要保存方法的字节码,操作数栈和该方法的栈帧,异常表。

举例:

classLava{ privateintspeed=5; voidflow(){} classVolcano{ publicstaticvoidmain(String[]args){ Lavalava=newLava(); lava.flow(); } }

运行命令JavaVolcano;

(1)JVM找到Volcano.class倒入,并提取相应的类型信息到方法区。通过执行方法区中的字节码,JVM执行main()方法,(执行时会一直保存指向Vocano类的常量池的指针)

(2)Main()中***条指令告诉JVM需为列在常量池***项的类分配内存(此处再次说明了常量池并非只存储常量信息),然后JVM找到常量池的***项,发现是对Lava类的符号引用,则检查方法区,看Lava类是否装载,结果是还未装载,则查找“Lava.class”,将类型信息写入方法区,并将方法区Lava类信息的指针来替换Volcano原常量池中的符号引用,即用直接引用来替换符号引用。

(3)JVM看到new关键字,准备为Lava分配内存,根据Volcano的常量池的***项找到Lava在方法区的位置,并分析需要多少对空间,确定后,在堆上分配空间,并将speed变量初始为0,并将lava对象的引用压到栈中

(4)调用lava的flow()方法

好了,大致了解了方法区的内容后,让我们来看看堆

Java对象的堆实现:

Java对象主要由实例变量(包括自己所属的类和其父类声明的)以及指向方法区中类数据的指针,指向方法表的指针,对象(非必需),等待集合(非必需),GC相关的数据(非必需)(主要视GC算法而定,如对于标记并清除算法,需要标记对象是否被引用,以及是否已调用finalize()方法)。

那么为什么Java对象中要有指向类数据的指针呢?我们从几个方面来考虑

首先:当程序中将一个对象引用转为另一个类型时,如何检查转换是否允许?需用到类数据

其次:动态绑定时,并不是需要引用类型,而是需要运行时类型,

这里的迷惑是:为什么类数据中保存的是实际类型,而非引用类型?这个问题先留下来,我想在后续的读书笔记中应该能明白

指向方法表的指针:这里和c++的VTBL是类似的,有利于提高方法调用的效率

对象锁:用来实现多个线程对共享数据的互斥访问

等待集合:用来让多个线程为完成共同目标而协调功过。(注意Object类中的wait(),notify(),notifyAll()方法)。

Java数组的堆实现:数组也拥有一个和他们的类相关联的Class实例,具有相同dimension和type的数组是同一个类的实例。数组类名的表示:如[[LJava/lang/Object表示Object[][],[I表示int[],[[[B表示byte[][][]

至此,堆已大致介绍完毕,下面来介绍程序计数器和Java栈

程序计数器:为每个线程独有,在线程启动时创建,

若thread执行Java方法,则PC保存下一条执行指令的地址。

若thread执行native方法,则Pc的值为undefined

Java栈:Java栈以帧为单位保存线程的运行状态,Java栈只有两种操作,帧的压栈和出栈。

每个帧代表一个方法,Java方法有两种返回方式,return和抛出异常,两种方式都会导致该方法对应的帧出栈和释放内存。

帧的组成:局部变量区(包括方法参数和局部变量,对于instance方法,还要首先保存this类型,其中方法参数按照声明顺序严格放置,局部变量可以任意放置),操作数栈,帧数据区(用来帮助支持常量池的解析,正常方法返回和异常处理)。

本地方法栈:依赖于本地方法的实现,如某个JVM实现的本地方法借口使用C连接模型,则本地方法栈就是C栈,可以说某线程在调用本地方法时,就进入了一个不受JVM限制的领域,也就是JVM可以利用本地方法来动态扩展本身。

相信大家都明白JVM是什么了吧。

看完上述内容,你们掌握如何深度解析JVM的方法了吗?如果还想学到更多技能或想了解更多相关内容,欢迎关注编程网精选频道,感谢各位的阅读!

--结束END--

本文标题: 如何深度解析JVM

本文链接: https://www.lsjlt.com/news/288828.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • 如何深度解析JVM
    如何深度解析JVM,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。首先这里澄清两个概念:JVM实例和JVM执行引擎实例,JVM实例对应了一个独立运行的Java程序,而JVM执行引...
    99+
    2023-06-17
  • 如何深度分析jvm中dump文件
    这篇文章将为大家详细讲解有关如何深度分析jvm中dump文件,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。JVM dumpjava内存dump是jvm运行时内存的一份快照,利用它可以分析是否...
    99+
    2023-06-16
  • 如何深度解析Kafka
    如何深度解析Kafka,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。背景介绍Kafka简介Kafka是一种分布式的,基于发布/订阅的消息系统。主要设计目标如下:...
    99+
    2023-06-17
  • 如何深入解析JVM ClassLoader相关知识
    如何深入解析JVM ClassLoader相关知识,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。深入JVM:关于ClassLoader的一些知识一.什么是ClassLoad...
    99+
    2023-06-17
  • ApacheFlink中如何深度解析FaultTolerance
    ApacheFlink中如何深度解析FaultTolerance,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。摘要:实际问题 在流计算场景中,数据会源源不断的流入Apache ...
    99+
    2023-06-19
  • 超详细的JVM 深入解析
    工作之余,想总结一下JVM相关知识。Java运行时数据区:Java虚拟机在执行Java程序的过程中会将其管理的内存划分为若干个不同的数据区域,这些区域有各自的用途、创建和销毁的时间,有些区域随虚拟机进程的启动而存在,有些区域则是依赖用户线程...
    99+
    2023-06-02
  • 如何深度解析java8新特性Optional
    本篇文章为大家展示了如何深度解析java8新特性Optional,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。 下面以jdk1.8.0_111源码为例 publ...
    99+
    2024-04-02
  • 如何深入了解JVM内存结构
    如何深入了解JVM内存结构,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。你对JVM内存结构是否熟悉,这里向大家描述一下,主要包括类装载子系统,方法区,PC寄存器...
    99+
    2023-06-17
  • Spring cache源码深度解析
    目录前言题外话:如何阅读开源代码?核心类图源码分析(带注释解释)1、解析注解2、逻辑执行总结前言 Spring cache是一个缓存API层,封装了对多种缓存的通用操作,可以借助注解...
    99+
    2024-04-02
  • Java 8 - Optional类深度解析
    对Java 8 Optional类进行深度解析。 @pdaiJava 8 - Optional类深度解析Optional类包含的方法ofofNullableisPresentgetifPresentorElseorElseGetorElse...
    99+
    2022-12-02
    java框架 java全栈 java学习路线 java全栈知识 java面试 知识体系 java技术体系 java编程
  • 一文深度讲解JVM 内存分析工具 MAT及实践(建议收藏)
    前言 熟练掌握 MAT 是 Java 高手的必备能力,但实践时大家往往需面对众多功能,眼花缭乱不知如何下手,小编也没有找到一篇完善的教学素材,所以整理本文帮大家系统掌握 MAT 分析工具。 本文详细讲解 MAT 众多内存分析工具功能,这些...
    99+
    2023-09-13
    jvm java 算法
  • 怎么深度剖析JDK和JRE以及JVM三者的区别
    本篇文章为大家展示了怎么深度剖析JDK和JRE以及JVM三者的区别,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。你对jdk,jre,jvm三者的区别和联系是否了解,这里和大家分享一下, j2sdk(...
    99+
    2023-06-17
  • 如何深度剖析Python语言特点
    这期内容当中小编将会给大家带来有关如何深度剖析Python语言特点,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。这里并不涉及python的特殊规则和细节,目标是通过示例使你快速了解Python语言的特点。...
    99+
    2023-06-17
  • ElasticSearch 深度分页示例解析
    目录1 前言2 from + size 分页方式2.1 Query 阶段2.2 Fetch 阶段2.3 ES 示例2.4 实现示例2.5 小结3 Scroll 分页方式3.1 执行过...
    99+
    2023-02-22
    ElasticSearch 深度分页 ElasticSearch 分页
  • Springjcl及springcore源码深度解析
    目录1.spring-jcl1.1.日志加载2.spring-core2.1.目录结构2.2.源码说明2.2.1.asm类解读2.2.2.core2.2.3.util2.2.4.cg...
    99+
    2022-11-13
    Spring jcl spring core Spring 源码解析
  • 如何解析JVM内存区域组成
    这篇文章将为大家详细讲解有关如何解析JVM内存区域组成,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。在方法(代码块)中定义一个变量时,java就在栈中为这个变量分配JVM内存空间,当超过变量...
    99+
    2023-06-17
  • 深入浅析Java中 JVM的原理
    这篇文章将为大家详细讲解有关深入浅析Java中 JVM的原理,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。JVM是一种用于计算设备的规范,它是一个虚构出来的计算机,是通过在实际的计算机上仿真...
    99+
    2023-05-31
    java jvm ava
  • 深度解析Python线程和进程
    目录什么是进程什么是线程线程与进程的区别并行与并发Python中的多进程Python中进程操作线程Python的threading模块锁Lock:全局解释器锁(GIL)参考文章:什么...
    99+
    2024-04-02
  • 深度解析Java中ArrayList的使用
    目录一、ArrayList是什么二、ArrayList的构造方法三、ArrayList的常见方法常见方法遍历ArrayList使用迭代器删除元素四、ArrayList的扩容机制一、A...
    99+
    2024-04-02
  • pyTorch深度学习softmax实现解析
    目录用PyTorch实现linear模型模拟数据集定义模型加载数据集optimizer模型训练softmax回归模型Fashion-MNISTcross_entropy模型的实现利用...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作