浅析Java虚拟机结构与机制 (下)

时间:2021-07-16 | 标签: | 作者:Q8 | 来源:网络

小提示:您能找到这篇{浅析Java虚拟机结构与机制 (下)}绝对不是偶然,我们能帮您找到潜在客户,解决您的困扰。如果您对本页介绍的浅析Java虚拟机结构与机制 (下)内容感兴趣,有相关需求意向欢迎拨打我们的服务热线,或留言咨询,我们将第一时间联系您!

   本文主要介绍JVM的组成部分以及它们内部工作的机制和原理。在研究JVM的过程中会发现,其实JVM本身就是一个计算机体系结构,很多原理和我们平时的硬件、微机原理、 操作系统都有十分相似的地方,所以学习JVM本身也是加深自我对计算机结构认识的一个很好的途径。





  四、本地方法栈(Native Method Stack)
  本地方法栈类似于Java栈,主要存储了本地方法调用的状态。在Sun JDK中,本地方法栈和Java栈是同一个。
  五、方法区(Method Area)
  类型信息和类的静态变量都存储在方法区中。方法区中对于每个类存储了以下数据:
  a.类及其父类的全限定名(java.lang.Object没有父类)
  b.类的类型(Class or Interface)
  c.访问修饰符(public, abstract, final)
  d.实现的接口的全限定名的列表
  e.常量池
  f.字段信息
  g.方法信息
  h.静态变量
  i.ClassLoader引用
  j.Class引用
  可见类的所有信息都存储在方法区中。由于方法区是所有线程共享的,所以必须保证线程安全,举例来说,如果两个类同时要加载一个尚未被加载的类,那么一个类会请求它的ClassLoader去加载需要的类,另一个类只能等待而不会重复加载。
  此外为了加快调用方法的速度,通常还会为每个非抽象类创建私有的方法表,方法表是一个数组,存放了实例可能被调用的实例方法的直接引用。方法表对于多态有非常重要的意义,具体可以参照《浅谈多态机制的意义及实现》一文中“多态的实现”一节。
  在Sun JDK中,方法区对应了持久代(Permanent Generation),默认最小值为16MB,最大值为64MB。
  六、堆(Heap)
  堆用于存储对象实例以及数组值。堆中有指向类数据的指针,该指针指向了方法区中对应的类型信息。堆中还可能存放了指向方法 表的指针。堆是所有线程共享的,所以在进行实例化对象等操作时,需要解决同步问题。此外,堆中的实例数据中还包含了对象锁,并且针对不同的垃圾收集策略, 可能存放了引用计数或清扫标记等数据。
  在堆的管理上,Sun JDK从1.2版本开始引入了分代管理的方式。主要分为新生代、旧生代。分代方式大大改善了垃圾收集的效率。
  1、新生代(New Generation)
  大多数情况下新对象都被分配在新生代中,新生代由Eden Space和两块相同大小的Survivor Space组成,后两者主要用于Minor GC时的对象复制(Minor GC的过程在此不详细讨论)。
  JVM在Eden Space中会开辟一小块独立的TLAB(Thread Local Allocation Buffer)区域用于更高效的内存分配,我们知道在堆上分配内存需要锁定整个堆,而在TLAB上则不需要,JVM在分配对象时会尽量在TLAB上分配,以提高效率。
  2、旧生代(Old Generation/Tenuring Generation)
  在新生代中存活时间较久的对象将会被转入旧生代,旧生代进行垃圾收集的频率没有新生代高。
  七、执行引擎
  执行引擎是JVM执行Java字节码的核心,执行方式主要分为解释执行、编译执行、自适应优化执行、硬件芯片执行方式。
  JVM的指令集是基于栈而非寄存器的,这样做的好处在于可以使指令尽可能紧凑,便于快速地在网络上传输(别忘了Java最初就是为网络设计的),同 时也很容易适应通用寄存器较少的平台,并且有利于代码优化,由于Java栈和PC寄存器是线程私有的,线程之间无法互相干涉彼小程序好吗此的栈。每个线程拥有独立的 JVM执行引擎实例。
  J快手赚钱VM指令由单字节操作码和若干操作数组成。对于需要操作数的指令,通常是先把操作数压入操作数栈,即使是对局部变量赋值,也会先入栈再赋值。注意这里是“通常”情况,之后会讲到由于优化导致的例外。
  1、解释执行
  和一些动态语言类似,JVM可以解释执行字节码。Sun JDK采用了token-threading的方式,感兴趣的同学可以深入了解一下。
  解释执行中有几种优化方式:
  a.栈顶缓存
  将位于操作数栈顶的值直接缓存在寄存器上,对于大部分只需要一个操作数的指令而言,就无需再入栈,可以直接在寄存器上进行计算,结果压入操作数站。这样便减少了寄存器和内存的交换开销。
  b.部分栈帧共享
  被调用方法可小红书直播优势将调用方法栈帧中的操作数栈作为自己的局部变量区,这样在获取方法参数时减少了复制参数的开销。
  c.执行机器指令
  在一些特殊情况下,JVM会执行机器指令以提高速度。
  2、编译执行
  为了提升执行速度,Sun JDK提供了将字节码编译为机器指令的支持,主要利用了JIT(Just-In-Time)编译器在运行时进行编译,它会在第一次执行时编译字节码为机器码并缓存,之后就可以重复利用。Oracle JRockit采用的是完全的编译执行。
  3、自适应优化执行
  自适应优化执行的思想是程序中10%~20%的代码占据了80%~90%的执行时间,所以通过将那少部分代码编译为优化过 的机器码就可以大大提升执行效率。自适应优化的典型代表是Sun的Hotspot VM,正如其名,JVM会监测代码的执行情况,当判断特定方法是瓶颈或热点时,将会启动一个后台线程,把该方法的字节码编译为极度优化的、静态链接的 C++代码。当方法不再是热区时,则会取消编译过的代码,重新进行解释执行。
  自适应优化不仅通过利用小部分的编译时间获得大部分的效率提升,而且由于在执行过程中时刻监测,对内联代码等优化也起到了很大的作用。由于面向对象的多态性,一个方法可能对应了很多种不同实现,自适应优化就可以通过监测只内联那些用到的代码,大大减少了内联函数的大小。
  Sun JDK在编译上采用了两种模式:Client和Server模式。前者较为轻量级,占用内存较少。后者的优化程序更高,占用内存更多。
  在Server模式中会进行对象的逃逸分析,即方法中的对象是否会在方法外使用,如果被其它方法使用了,则该对象是逃逸的。对于非逃逸对象,JVM 会在栈上直接分配对象(所以对象不一定是在堆上分配的),线程获取对象会更加快速,同时当方法返回时,由于栈帧被抛弃,也有利于对象的垃圾收集。 Server模式还会通过分析去除一些不必要的同步,感兴趣的同学可以研究一下Sun JDK 6引入的Biased Locking机制。
  此外,执行引擎也必须保证线程安全性,因而JMM(Java Memory Model)也是由执行引擎确保的。
浅析Java虚拟机结构与机制 (下)

上一篇:误删除虚拟机磁盘文件,如何恢复
下一篇:浅析Java虚拟机结构与机制 (上)


版权声明:以上主题为“浅析Java虚拟机结构与机制 (下)"的内容可能是本站网友自行发布,或者来至于网络。如有侵权欢迎联系我们客服QQ处理,谢谢。
相关内容
扫码咨询
    浅析Java虚拟机结构与机制 (下)
    打开微信扫码或长按识别二维码

小提示:您应该对本页介绍的“浅析Java虚拟机结构与机制 (下)”相关内容感兴趣,若您有相关需求欢迎拨打我们的服务热线或留言咨询,我们尽快与您联系沟通浅析Java虚拟机结构与机制 (下)的相关事宜。

关键词:浅析Java虚拟机结构与机制

关于 | 业务 | 案例 | 免责 | 隐私
客服邮箱:545321@QQ.com
电话:400-021-1330 | 客服QQ:545321
沪ICP备12034177号 | 沪公网安备31010702002418号