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

  要对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/

深入Java虚拟机之虚拟机体系结构相关推荐

  1. 第 1 章 一 JVM 和 Java 体系架构 (虚拟机介绍、字节码、Java跨平台性)

    第 1 章 JVM 和 Java 体系架构 1.JVM 前言 作为Java工程师, 你是否也遇到过这些问题? 运行着的线上系统突然卡死,系统无法访问,甚至直接OOM! 想解决线上JVM GC问题,但却 ...

  2. Java之Java程序与虚拟机

    Java为什么要在虚拟机中运行 简单的来说,Java作为一门高级程序语言,语法复杂,抽象度高,不能直接翻译为机器码在机器上运行,所以设计者就设计了虚拟机,通过编译器将Java程序转换成虚拟机所能识别的 ...

  3. java 实现VMware虚拟机创建

    根据vim25.jar 提供的虚拟机创建任务接口 VimPortType.createVMTask(),可以实现满足自己配置需求的一个虚拟机, 而且 VMware 在其提供的 vSphereSDK 提 ...

  4. JVM之Java发展史,虚拟机发展史,java编译方式

    java技术体系包括了几个组成部分? 可以看成 5 个部分呢,给你一个图自己看吧,太简单了呢~ javaME.SE.EE分别是什么呀? ①.ME 是支持Java程序在 移动终端 上的平台,JDK6之前 ...

  5. java虚拟机 hotspot_java虚拟机HotSpot

    没错,Java是解释语言,但并不意味着它一定被解释执行.早期 的虚拟机确实一条一条指令解释执行,但人们发现这样效率太低, 不满足各种要求,因此出现了许多其它虚拟机,如JIT的虚拟机. HotSpot也 ...

  6. 解决虚拟机vmware虚拟机安装64位系统“此主机支持 Intel VT-x,但 Intel VT-x 处于禁用状态”的问题

    解决虚拟机vmware虚拟机安装64位系统"此主机支持 Intel VT-x,但 Intel VT-x 处于禁用状态"的问题 参考文章: (1)解决虚拟机vmware虚拟机安装64 ...

  7. 虚拟机建立快照_使用qmeu-img创建虚拟机(创建虚拟机,虚拟机快照)

    使用qmeu-img管理虚拟机磁盘镜像(创建虚拟机,虚拟机快照) 一台虚拟机的核心就是一个磁盘镜像,这个镜像可以理解成虚拟机的磁盘,里面有虚拟机的操作系统和驱动等重要文件.本文主要介绍创建虚拟机的一般 ...

  8. 安装arm虚拟机_虚拟机Parallels出手:苹果M1的Mac能运行Win 10 还挺顺畅

    对于搭载M1处理器的苹果新Mac来说,终于可以用上Windows 10了. Mac平台知名虚拟化软件Parallels宣布,新的Parallels Desktop 16 for M1 Mac技术预览版 ...

  9. 虚拟机:虚拟机三种网络连接

    前言 很多人安装虚拟机的时候,经常遇到不能上网的问题,而vmware有三种网络模式,对初学者来说也比较眼花聊乱,今天我就来基于虚拟机3种网络模式,帮大家普及下虚拟机上网的背景知识. 虚拟机网络模式 无 ...

  10. Hyper-V导出虚拟机/导入虚拟机步骤(克隆),以及克隆之后设置静态IP无效的解决办法

    目录 导出虚拟机 导入虚拟机 重点来了:克隆之后设置静态IP无效 解决克隆之后设置静态IP无效 在做微服务项目时,经常会用到多台机器来搭建服务环境.在不想一台一台虚拟机创建的情况下,克隆虚拟机是最好的 ...

最新文章

  1. shell脚本编程之控制脚本
  2. 用gulp构建你的前端项目
  3. hive 写入mysql 覆盖_替换Hive的元数据库derby
  4. Confluence 6 CSS 编辑快速入门
  5. Redis简介和Redis Template用法整理
  6. Java继承概述以及Java继承案例和继承的好处
  7. jpa jsf_完整Web应用程序Tomcat JSF Primefaces JPA Hibernate –第2部分
  8. php mysql 权重_PHP对MySql的常用操作
  9. Understanding .NET Code Access Security
  10. Tensorflow手写数字识别
  11. 数据结构与算法——算法知识总览
  12. android模拟器的录屏,夜神安卓模拟器如何录制视频
  13. 台电平板teclast X16HD碎屏拆机更换日志
  14. 《大学物理》课程考试大纲
  15. 【数字逻辑与数字系统设计】应对期末考(更新于2022/4/15)
  16. 街霸 彩虹 m7 android,街霸2四大天王M7
  17. python程序中如何合理处理[WinError 5]拒绝访问的错误
  18. 万有(惠州)国际旅游度假区项目落户惠州
  19. fagin 启动报错 Fallback/fallbackFactory
  20. 关于智能家居开源平台(如Home Assistant)——智汀家庭云,你需要知道的是

热门文章

  1. [转载] 杜拉拉升职记——02 单相思与性骚扰
  2. Javascript原型链
  3. .Net Framework 3.0 概述
  4. Eigen/Matlab 使用小结
  5. c, c++函数名编译符号修饰符说明
  6. expires与etag控制页面缓存的优先级
  7. 锦上添花DataGrid!
  8. DataGrid中自带的分页功能的使用
  9. 支持向量机(SVM)简介
  10. 二维码Aztec简介及其解码实现(zxing-cpp)