深入Java虚拟机之虚拟机体系结构

简介:

工作以来,代码越写越多,程序也越来越臃肿,效率越来越低,对于我这样一个追求完美的程序员来说,这是绝对不被允许的,于是除了不断优化程序结构外,内存优化和性能调优就成了我惯用的“伎俩”。

  要对Java程序进行内存优化和性能调优,不了解虚拟机的内部原理(或者叫规范更严谨一点)是肯定不行的,这里推荐一本好书《深入Java虚拟机(第二版)》(Bill Venners著,曹晓刚 蒋靖 译,实际上本文正是作者阅读本书之后,对Java虚拟机的个人理解阐述)。当然了,了解Java虚拟机的好处并不仅限于上述两点好处。从更深一点的技术层面上看,了解Java虚拟机的规范和实现,将更加有助于我们编写高效、稳定的Java代码。比如,假如了解Java虚拟机的内存模型,了解虚拟机的内存回收机制,那么我们就不会过分依赖它,而会在需要的时候显式的"释放内存"(Java代码不能显式释放内存,但是可以通过释放对象引用告知垃圾回收器回收该对象需要被回收),以降低不必要的内存消耗;假如我们了解Java栈的工作原理,那么我们就可以通过减少递归层数,减少循环次数来降低堆栈溢出的风险。可能对于应用开发人员来说,可能不会直接去涉及这些Java虚拟机底层实现的工作,但是了解这些背景知识,或多或少,都会对我们写的程序产生潜移默化的好的影响。

  本篇文章,将简明扼要的说明Java虚拟机的体系结构和内存模型,如有用词不妥或解释不准确之处,请不吝指正,深感荣幸!

  Java 虚拟机体系结构

  类装载子系统

  Java虚拟机有两种类装载器,分别是启动类装载器和用户自定义装载器。

  通类装载子系统通过类的全限定名(包名和类名,网络装载还包括 URL)将 Class 装载进运行时数据区。对于每一个被装载的类型,Java虚拟机都会创建一个java.lang.Class类的实例来代表该类型,该实例被放在内存中的堆区,而装载的类型信息则位于方法区,这一点和所有其他对象都是一样的。

  类装载子系统在装载一个类型前,除了要定位和导入对应的二进制class文件外,还要验证导入类的正确性,为类变量分配并初始化内存,以及解析符号引用为直接引用,这些动作严格按照以下顺序进行:

  1)装载——查找并装载类型的二进制数据;

  2)连接——执行验证,准备以及解析(可选)

  3)验证 确保被导入类型的正确性

  4)准备 为类变量分配内存,并将其初始化为默认值

  5)解析 把类型中的符号引用转换为直接应用

  方法区

  对于每一个被类装载子系统装载的类型,虚拟机都会保存下列数据到方法区:

  ◆  类型的全限定名

  ◆ 类型超类的全限定名(java.lang.Object没有超类)

  ◆ 类型是类类型还是接口类型

  ◆ 类型的访问修饰符

  ◆ 任何直接超接口的全限定名有序列表

 除了上述基本类型信息,还将保存如下信息:

  ◆ 类型的常量池

  ◆ 字段信息(包括字段名、字段类型、字段修饰符)

  ◆ 方法信息(包括方法名、返回类型、参数的数量和类型、方法修饰符,如果方法不是抽象和本地的,还将保存方法的字节码、操作数栈和该方法栈帧中的局部变量区的大小和异常表)

  ◆ 常量以外的所有类变量(其实就是类的静态变量,因为静态变量是所有实例共享的,且与类型直接相关,所以他们是类一级的变量,作为类的成员被保存在方法区)

  一个到类ClassLoader的引用

  • //返回的就是刚才保存的ClassLoader引用   
  • String.class.getClassLoader();
  •   一个到Class类的引用

  • //将返回刚才保存的Class类的引用   
  • String.class;
  •   注意,方法区也是可以被垃圾回收器回收的。

      堆

      Java程序在运行时创建的所有类实例或数组都放在同一个堆中,而每一个Java虚拟机也是有一个对空间,所有线程共享一个堆(这就是一个多线程的Java程序会产生对象访问的同步问题的原因了)。

      由于每一种Java虚拟机都有对虚拟机规范的不同实现,所以我们可能不知道每一种Java虚拟机在堆中是以何种形式表示对象实例的,不过我们可以通过下面这可能的实现来一窥端倪:


      程序计数器

      对于运行中的Java程序而言,每一个线程都有自己的PC(程序计数器)寄存器,它是在该线程启动时创建的,大小为一个字长,用来保存需要被执行的下一行代码的位置。

      Java栈

      每一个线程都有一个Java栈,以栈帧为单位保存线程的运行状态。虚拟机对Java栈的操作有两种:压栈和出栈,二者都已帧为单位。栈帧保存了传入参数、局部变量、中间运算结果等数据,在方法完成时被弹出,然后释放。

      看一下两个局部变量相加时栈帧的内存快照

      本地方法栈

      这是 Java 调用操作系统本地库的地方,用来实现 JNI(Java Native Interface,Java 本地接口)

      执行引擎

      Java虚拟机的核心,控制装入 Java 字节码并解析;对于运行中的Java程序而言,每一个线程都是一个独立的虚拟机执行引擎的实例,从线程生命周期的开始到结束,他要么在执行字节码,要么在执行本地方法。

      本地接口

      连接了本地方法栈和操作系统库。

      注:文中所有提到“Java虚拟机”的地方都是指“JavaEE和JavaSE平台的Java虚拟机规范”。


    本文出自seven的测试人生公众号最新内容请见作者的GitHub页:http://qaseven.github.io/

    目录
    相关文章
    |
    6月前
    |
    监控 算法 Java
    Java虚拟机(JVM)的垃圾回收机制深度解析####
    本文深入探讨了Java虚拟机(JVM)的垃圾回收机制,旨在揭示其背后的工作原理与优化策略。我们将从垃圾回收的基本概念入手,逐步剖析标记-清除、复制算法、标记-整理等主流垃圾回收算法的原理与实现细节。通过对比不同算法的优缺点及适用场景,为开发者提供优化Java应用性能与内存管理的实践指南。 ####
    |
    5月前
    |
    监控 算法 Java
    Java虚拟机(JVM)垃圾回收机制深度剖析与优化策略####
    本文作为一篇技术性文章,深入探讨了Java虚拟机(JVM)中垃圾回收的工作原理,详细分析了标记-清除、复制算法、标记-压缩及分代收集等主流垃圾回收算法的特点和适用场景。通过实际案例,展示了不同GC(Garbage Collector)算法在应用中的表现差异,并针对大型应用提出了一系列优化策略,包括选择合适的GC算法、调整堆内存大小、并行与并发GC调优等,旨在帮助开发者更好地理解和优化Java应用的性能。 ####
    125 0
    |
    9月前
    |
    Java Docker 索引
    记录一次索引未建立、继而引发一系列的问题、包含索引创建失败、虚拟机中JVM虚拟机内存满的情况
    这篇文章记录了作者在分布式微服务项目中遇到的一系列问题,起因是商品服务检索接口测试失败,原因是Elasticsearch索引未找到。文章详细描述了解决过程中遇到的几个关键问题:分词器的安装、Elasticsearch内存溢出的处理,以及最终成功创建`gulimall_product`索引的步骤。作者还分享了使用Postman测试接口的经历,并强调了问题解决过程中遇到的挑战和所花费的时间。
    |
    5月前
    |
    存储 监控 算法
    深入探索Java虚拟机(JVM)的内存管理机制
    本文旨在为读者提供对Java虚拟机(JVM)内存管理机制的深入理解。通过详细解析JVM的内存结构、垃圾回收算法以及性能优化策略,本文不仅揭示了Java程序高效运行背后的原理,还为开发者提供了优化应用程序性能的实用技巧。不同于常规摘要仅概述文章大意,本文摘要将简要介绍JVM内存管理的关键点,为读者提供一个清晰的学习路线图。
    |
    5月前
    |
    存储 监控 算法
    Java虚拟机(JVM)垃圾回收机制深度解析与优化策略####
    本文旨在深入探讨Java虚拟机(JVM)的垃圾回收机制,揭示其工作原理、常见算法及参数调优方法。通过剖析垃圾回收的生命周期、内存区域划分以及GC日志分析,为开发者提供一套实用的JVM垃圾回收优化指南,助力提升Java应用的性能与稳定性。 ####
    |
    7月前
    |
    Java
    jvm复习,深入理解java虚拟机一:运行时数据区域
    这篇文章深入探讨了Java虚拟机的运行时数据区域,包括程序计数器、Java虚拟机栈、本地方法栈、Java堆、方法区、元空间和运行时常量池,并讨论了它们的作用、特点以及与垃圾回收的关系。
    121 19
    jvm复习,深入理解java虚拟机一:运行时数据区域
    |
    6月前
    |
    机器学习/深度学习 监控 算法
    Java虚拟机(JVM)的垃圾回收机制深度剖析####
    本文深入探讨Java虚拟机(JVM)的垃圾回收机制,揭示其工作原理、常见算法、性能调优策略及未来趋势。通过实例解析,为开发者提供优化Java应用性能的思路与方法。 ####
    124 1
    |
    6月前
    |
    监控 Java 开发者
    Java虚拟机(JVM)深度优化指南####
    本文深入探讨了Java虚拟机(JVM)的工作原理及其性能优化策略,旨在帮助开发者通过理解JVM的内部机制来提升Java应用的运行效率。不同于传统的技术教程,本文采用案例分析与实战技巧相结合的方式,为读者揭示JVM调优的艺术。 ####
    174 8
    |
    7月前
    |
    存储 算法 Java
    Java虚拟机(JVM)的内存管理与性能优化
    本文深入探讨了Java虚拟机(JVM)的内存管理机制,包括堆、栈、方法区等关键区域的功能与作用。通过分析垃圾回收算法和调优策略,旨在帮助开发者理解如何有效提升Java应用的性能。文章采用通俗易懂的语言,结合具体实例,使读者能够轻松掌握复杂的内存管理概念,并应用于实际开发中。
    |
    6月前
    |
    监控 算法 Java
    深入理解Java虚拟机(JVM)的垃圾回收机制
    【10月更文挑战第21天】 本文将带你深入了解Java虚拟机(JVM)的垃圾回收机制,包括它的工作原理、常见的垃圾收集算法以及如何优化JVM垃圾回收性能。通过本文,你将对JVM垃圾回收有一个全新的认识,并学会如何在实际开发中进行有效的调优。
    142 0

    热门文章

    最新文章