`

高手详细介绍JVM是什么?

    博客分类:
  • java
 
阅读更多

高手详细介绍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)子系统,运行时数据区,和执行引擎。下面将先介绍类装载器,然后是执行引擎,最后是运行时数据区

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

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

     用户自定义类装载器:

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

  1. protectedfinalClassdefineClass(Stringname,bytedata[],intoffset,intlength)   
  2. protectedfinalClassdefineClass(Stringname,bytedata[],intoffset,intlength,ProtectionDomainprotectionDomain);protectedfinalClassfindSystemClass(Stringname)   
  3. protectedfinalvoidresolveClass(Classc)  

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

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

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

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

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

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

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

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

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

     (二)执行技术

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

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

     3,运行时数据区:主要包括:方法区,堆,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将所有的常量复制至其常量池或者其字节码流中。

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

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

举例:

  1. classLava{   
  2. privateintspeed=5;   
  3. voidflow(){}   
  4. classVolcano{   
  5. publicstaticvoidmain(String[]args){   
  6. Lavalava=newLava();   
  7. lava.flow();   
  8. }   
  9. }  

 

 

运行命令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是什么了吧。

 

转自:http://www.xjit.net/java/jvm/2011/33458.html

分享到:
评论

相关推荐

    模拟IC设计领域:环形振荡器与锁相环的设计、仿真及测试指南

    内容概要:本文详细介绍了环形振荡器(Ring VCO)和锁相环(PLL)的设计、仿真与测试方法。针对初学者,提供了从基础电路理论到具体实操步骤的全面指导,涵盖了Cadence软件的使用、PSS/PNOISE仿真、调谐曲线绘制、相位噪声优化以及眼图调试等方面的内容。文中不仅讲解了基本概念和技术要点,还分享了许多实用的操作技巧和常见问题解决方案,如如何正确设置仿真参数、优化相位噪声、处理电源纹波等问题。此外,还附赠了一份详细的ADE_XL用户指南,帮助读者深入理解和掌握相关技术。 适合人群:对模拟IC设计感兴趣的初学者及有一定基础的研发人员。 使用场景及目标:①掌握环形振荡器的基本原理及其在Cadence中的仿真方法;②学会如何进行调谐曲线、相位噪声等关键性能指标的仿真与优化;③提高解决实际工程问题的能力,如电源纹波抑制、眼图调试等。 其他说明:本文特别强调了实践经验的重要性,鼓励读者动手实践并在实践中不断积累经验。同时提醒读者注意一些容易忽视但至关重要的细节,如仿真参数的选择和特殊条件下可能出现的问题。

    【java】基于Java+Springboot+Vue的社区医院管理系统(源代码+数据库+万字论文).zip

    【java】基于Java+Springboot+Vue的社区医院管理系统(源代码+数据库+万字论文).zip

    scratch少儿编程逻辑思维游戏源码-大盗之魂.zip

    scratch少儿编程逻辑思维游戏源码-大盗之魂.zip

    scratch少儿编程逻辑思维游戏源码-弹跳猫.zip

    scratch少儿编程逻辑思维游戏源码-弹跳猫.zip

    scratch少儿编程逻辑思维游戏源码-城堡逃脱.zip

    scratch少儿编程逻辑思维游戏源码-城堡逃脱.zip

    基于马里兰电池数据集的RNN与LSTM电池剩余寿命(RUL)预测研究

    内容概要:本文探讨了马里兰电池数据集及其在电池剩余寿命(RUL)预测中的应用,重点介绍了RNN(循环神经网络)和LSTM(长短期记忆网络)这两种深度学习模型的应用。文章首先概述了马里兰电池数据集的特点,它记录了电池在不同环境和使用条件下的关键指标变化,为电池寿命预测提供了宝贵的数据支持。接着,文章详细解释了RNN和LSTM模型的工作原理以及它们在处理序列数据方面的优势,特别是LSTM在处理长时间依赖关系时表现出色。随后,通过一个简单的Python代码示例,展示了如何使用Keras库构建LSTM模型来进行RUL预测,包括数据预处理、模型构建、编译、训练和预测的具体步骤。最后,文章总结了RNN和LSTM模型在电池RUL预测中的重要性和潜力,并展望了未来的研究方向。 适合人群:对电池技术和机器学习感兴趣的科研人员、工程师及学生。 使用场景及目标:适用于希望利用深度学习技术提升电池管理系统的准确性和效率的人群。主要目标是通过学习历史数据,预测电池未来的状态,从而为新电池设计和现有电池维护提供科学依据。 其他说明:文中提供的代码示例仅作为入门指南,实际应用中需要根据具体情况调整模型结构和参数设置,并可能需要高性能计算资源来加速训练过程。

    scratch少儿编程逻辑思维游戏源码-道场战场:战斗模拟器.zip

    scratch少儿编程逻辑思维游戏源码-道场战场:战斗模拟器.zip

    STM32低压无感BLDC方波方案全功能版:源码无库、脉冲注入、兼容国产芯片

    内容概要:本文详细介绍了基于STM32的低压无感BLDC(直流无刷电机)方波方案的全功能版本。该方案采用未封装库的源码,支持脉冲注入用于识别电机转子初始位置,并兼容国产芯片。文中提供了详细的硬件设计(包括原理图、丝印图)、软件实现(特别是脉冲注入和换相逻辑),以及调试方法和技巧。此外,还讨论了霍尔接口的兼容性和自动校准流程,确保系统能够适应不同类型的电机负载。 适合人群:具有一定嵌入式开发经验的研发人员和技术爱好者,尤其是对无感BLDC电机控制系统感兴趣的工程师。 使用场景及目标:①深入理解无感BLDC电机控制的底层逻辑;②掌握脉冲注入和换相逻辑的具体实现;③学习如何优化硬件设计和调试技巧,提高系统的可靠性和性能。 其他说明:该方案不仅适用于学术研究,也可应用于实际产品开发,帮助开发者快速搭建稳定的无感BLDC电机控制系统。

    【R语言数据分析】从环境配置到实战案例:涵盖数据处理、可视化与统计建模的综合教程

    内容概要:本文档是2025年R语言数据分析综合教程,详细介绍了从环境配置到实战案例的完整流程。首先,涵盖环境配置与基础操作,包括安装R语言及RStudio IDE、常用数据分析包的安装与加载、数据导入及基础操作如读取CSV/Excel文件、数据查看与清洗等。接着,深入数据探索与可视化,讲解单变量统计、多变量关系分析,并通过`ggplot2`包进行基础图表和高级图表绘制。然后,进入统计建模与高级分析部分,涉及线性回归模型的构建与评估、主成分分析的数据降维与可视化以及分类资料分析中的卡方检验等内容。最后,通过Palmer企鹅数据集分析和医疗数据分类分析两个实战案例,巩固所学知识。此外,还推荐了中文教程和实战拓展资源,如知乎专栏、CSDN文章、GitHub开源项目和Kaggle数据集等; 适合人群:对R语言数据分析感兴趣的初学者及有一定编程基础的数据分析师; 使用场景及目标:①掌握R语言环境搭建与基础操作技能;②学会利用R语言进行数据探索、可视化及统计建模;③通过实战案例提升解决实际问题的能力; 其他说明:文档内容循序渐进,理论与实践相结合,适合自学或教学使用,读者可根据自身需求选择重点学习内容。

    少儿编程scratch项目源代码文件案例素材-日本牛奶广告动画.zip

    少儿编程scratch项目源代码文件案例素材-日本牛奶广告动画.zip

    少儿编程scratch项目源代码文件案例素材-黏糊糊的圣诞节.zip

    少儿编程scratch项目源代码文件案例素材-黏糊糊的圣诞节.zip

    基于MATLAB的模块化多电平MMC-UPFC统一潮流控制器仿真模型及其在高压输电线路中的应用

    内容概要:本文详细介绍了基于MATLAB/Simulink平台构建的模块化多电平(MMC)统一潮流控制器(UPFC)仿真模型。首先探讨了MMC子模块的基本结构和电容电压均衡算法,接着讨论了环流抑制方法以及线路侧控制策略。文中还提供了具体的参数配置建议,如子模块数量、电容值、IGBT开关频率等,并展示了仿真的典型效果,包括电压提升和传输功率增加。此外,文章强调了该模型在新能源并网场景中的重要性和实用性。 适合人群:电力系统工程师、科研人员、高校师生等对高压输电线路和潮流控制感兴趣的读者。 使用场景及目标:适用于需要理解和掌握UPFC工作原理及其在MATLAB中的具体实现的研究人员和技术人员。目标是帮助读者搭建能够正常运行的仿真模型,理解UPFC在提高电力系统稳定性和灵活性方面的作用。 其他说明:文中提供的代码片段和参数设置有助于读者快速上手进行相关实验。同时,文章提到的谐波分析和性能评估方法也为进一步优化模型提供了指导。

    电力系统稳态仿真:基于Simulink的模型搭建与实践

    内容概要:本文详细介绍了如何利用Simulink搭建电力系统稳态仿真模型。首先从同步发电机的选择和参数设置入手,强调了惯性常数H和基底电压的重要性和具体配置方法。接着讨论了负荷模型的选择,推荐使用更贴近实际的ZIP负荷模型而非简单的恒定阻抗模型。然后深入探讨了潮流计算的关键步骤,特别是参考节点的设定及其对后续分析的影响。对于线路建模部分,则提倡采用分布参数线路模块并将其分割为多段以提高仿真的准确性。此外,还提到了一些高级应用,如启用相量仿真模式加速仿真速度以及应对可能出现的暂态不稳定情况的方法。最后鼓励尝试加入风电场元素,进一步研究新能源接入后的系统行为。 适合人群:从事电力系统研究、设计或维护的技术人员,尤其是那些希望深入了解Simulink工具箱在电力工程领域应用的专业人士。 使用场景及目标:适用于需要构建电力系统稳态仿真环境的研究项目或教学课程;旨在帮助用户掌握Simulink平台的基本操作技能,同时培养解决复杂电力网络问题的能力。 其他说明:文中提供了大量MATLAB/Simulink代码片段作为辅助材料,便于读者理解和实践相关概念和技术要点。

    scratch少儿编程逻辑思维游戏源码-地牢爬行者.zip

    scratch少儿编程逻辑思维游戏源码-地牢爬行者.zip

    少儿编程scratch项目源代码文件案例素材-南瓜小子.zip

    少儿编程scratch项目源代码文件案例素材-南瓜小子.zip

    少儿编程scratch项目源代码文件案例素材-日落之旅.zip

    少儿编程scratch项目源代码文件案例素材-日落之旅.zip

    scratch少儿编程逻辑思维游戏源码-弹回的球.zip

    scratch少儿编程逻辑思维游戏源码-弹回的球.zip

    scratch少儿编程逻辑思维游戏源码-电源竞技场.zip

    scratch少儿编程逻辑思维游戏源码-电源竞技场.zip

    少儿编程scratch项目源代码文件案例素材-山谷冲撞.zip

    少儿编程scratch项目源代码文件案例素材-山谷冲撞.zip

    scratch少儿编程逻辑思维游戏源码-洞穴冒险 2.zip

    scratch少儿编程逻辑思维游戏源码-洞穴冒险 2.zip

Global site tag (gtag.js) - Google Analytics