栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

一起学Java虚拟机(一),数据结构java语言描述百度云

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

一起学Java虚拟机(一),数据结构java语言描述百度云


我们可以把Java程序设计语言、Java虚拟机、Java类库这三部分统称为JDK(Java Development Kit),JDK是用于支持Java程序开发的最小环境。

JVM 是 JDK 的一部分,《Java 虚拟机规范》(The Java Virtual Machine Specification) 是平行于《Java 语言规范》(The Java Language Specification)的一套独立的规范,不同的公司对其有不同的实现 (类似于一个接口被不同的类实现)。

虚拟机始祖:Sun Classic/Exact VM
  • 世界上第一款商用Java虚拟机
  • 在JDK 1.2之前是JDK中唯一的虚拟机
  • JDK 1.4的时候,Classic VM才完全退出商用虚拟机的历史舞台被HotSpot取代
武林盟主:HotSpot VM
  • 是Sun/OracleJDK和OpenJDK中的默认Java虚拟机,也是目前使用范围最广的Java虚拟机
  • 如它名称中的HotSpot指的就是它的热点代码探测技术
  • 为全世界使用最广泛的Java虚拟机
小家碧玉:Mobile/Embedded VM
  • 面对移动和嵌入式市场,Java ME中的Java虚拟机
天下第二:BEA JRockit/IBM J9 VM
  • JRockit虚拟机曾经号称是“世界上速度最快的Java虚拟机”,是一款一款专门为服务器硬件和服务端应用场景高度优化的虚拟机。JRockit随着BEA被Oracle收购,现已不再继续发展
  • IBM J9虚拟机的市场定位与HotSpot比较接近,它是一款在设计上全面考虑服务端、桌面应用,再到嵌入式的多用途虚拟机
软硬合璧:BEA Liquid VM/Azul VM
  • 与特定硬件平台绑定、软硬件配合工作的专有虚拟机
挑战者:Apache Harmony/Google Android Dalvik VM
  • Apache Harmony是一个Apache软件基金会旗下以Apache License协议开源的实际兼容于JDK 5和JDK 6的Java程序运行平台,它含有自己的虚拟机和Java类库API,用户可以在上面运行Eclipse、Tomcat、Maven等常用的Java程序。
  • Dalvik虚拟机并不是一个Java虚拟机,它没有遵循《Java虚拟机规范》,不能直接执行Java的Class文件,使用寄存器架构而不是Java虚拟机中常见的栈架构。但是它与Java却又有着千丝万缕的联系,它执行的DEX(Dalvik Executable)文件可以通过Class文件转化而来,使用Java语法编写应用程序,可以直接使用绝大部分的Java API等。
Java内存区域划分与OutOfMemory

根据《Java虚拟机规范》的规定,Java虚拟机所管理的内存将会包括以下几个运行时数据区域:

程序计数器
  • 是当前线程所执行的字节码的行号指示器
  • 线程私有: 每条线程都需要有一个独立的程序计数器,各条线程之间计数器互不影响,独立存储
  • 如果线程正在执行的是一个Java方法,这个计数器记录的是正在执行的虚拟机字节码指令的地址;如果正在执行的是本地(Native)方法,这个计数器值则应为空(Undefined)
  • 没有OutOfMemory
Java虚拟机栈
  • 线程私有
  • 虚拟机栈描述的是Java方法执行的线程内存模型:每个方法被执行的时候,Java虚拟机都会同步创建一个栈帧(Stack frame)用于存储局部变量表、操作数栈、动态连接、方法出口等信息。每一个方法被调用直至执行完毕的过程,就对应着一个栈帧在虚拟机栈中从入栈到出栈的过程

  • 局部变量表存放了编译期可知的各种Java虚拟机基本数据类型(boolean、byte、char、short、int

《一线大厂Java面试题解析+后端开发学习笔记+最新架构讲解视频+实战项目源码讲义》

【docs.qq.com/doc/DSmxTbFJ1cmN1R2dB】 完整内容开源分享

、float、long、double)、对象引用(reference类型,它并不等同于对象本身,可能是一个指向对象起始地址的引用指针,也可能是指向一个代表对象的句柄或者其他与此对象相关的位置)和returnAddress类型(指向了一条字节码指令的地址)

  • 在《Java虚拟机规范》中,对这个内存区域规定了两类异常状况:如果线程请求的栈深度大于虚拟机所允许的深度,将抛出StackOverflowError异常;如果Java虚拟机栈容量可以动态扩展,当栈扩展时无法申请到足够的内存会抛出OutOfMemoryError异常
本地方法栈
  • 与虚拟机栈所发挥的作用相似,为虚拟机使用到的本地方法服务
Java堆
  • 是虚拟机所管理的内存中最大的一块
  • 所有的对象实例以及数组都应当在堆上分配
  • Java堆是被所有线程共享的一块内存区域
  • 所有线程共享的Java堆中可以划分出多个线程私有的分配缓冲区(Thread Local Allocation Buffer,TLAB)Java堆内存是线程共享的!面试官:你确定吗?
  • Java堆既可以被实现成固定大小的,也可以是可扩展的,不过当前主流的Java虚拟机都是按照可扩展来实现的(通过参数-Xmx和-Xms设定)。如果在Java堆中没有内存完成实例分配,并且堆也无法再扩展时,Java虚拟机将会抛出OutOfMemoryError异常。
方法区
  • 与Java堆一样,是各个线程共享的内存区域
  • 它用于存储已被虚拟机加载的类型信息、常量、静态变量、即时编译器编译后的代码缓存等数据
  • 在JDK 8完全废弃了永久代的概念,改用元空间来代替。
  • 运行时常量池是方法区的一部分。Class文件中除了有类的版本、字段、方法、接口等描述信息外,还有一项信息是常量池表(Constant Pool Table),用于存放编译期生成的各种字面量与符号引用,这部分内容将在类加载后存放到方法区的运行时常量池中
  • 运行期间也可以将新的常量放入池:比如String类的intern()方法
  • 如果方法区无法满足新的内存分配需求时,将抛出OutOfMemoryError异常。
直接内存
  • 并不是虚拟机运行时数据区的一部分,也不是《Java虚拟机规范》中定义的内存区域
  • 在JDK 1.4中新加入了NIO(New Input/Output)类,引入了一种基于通道(Channel)与缓冲区(Buffer)的I/O方式,它可以使用Native函数库直接分配堆外内存,然后通过一个存储在Java堆里面的DirectByteBuffer对象作为这块内存的引用进行操作。
  • 会受到本机总内存(包括物理内存、SWAP分区或者分页文件)大小以及处理器寻址空间的限制,而导致动态扩展时出现OutOfMemoryError异常
Hotspot虚拟机对象 对象的创建
  1. 当Java虚拟机遇到一条字节码new指令时,检查是否类已加载、解析、初始化,如果没有,则进行类加载
  2. 在类加载检查通过后,接下来虚拟机将为新生对象分配内存。
  3. 线程安全解决方案:1、CAS+失败重试保证更新操作的原子性 2、TLAB把内存分配的动作按照线程划分在不同的空间进行
  4. 内存分配完成之后,虚拟机必须将分配到的内存空间(但不包括对象头)都初始化为零值
  5. 接下来,Java虚拟机还要对对象进行必要的设置,例如这个对象是哪个类的实例、如何才能找到类的元数据信息、对象的哈希码(实际上对象的哈希码会延后到真正调用Object::hashCode()方法时才计算)、对象的GC分代年龄等信息。这些信息存放在对象的对象头(Object Header)之中。根据虚拟机当前运行状态的不同,如是否启用偏向锁等,对象头会有不同的设置方式。
  6. new指令之后会接着执行()方法,按照程序员的意愿对对象进行初始化,这样一个真正可用的对象才算完全被构造出来
对象的内存布局
  • 在堆内存中的存储布局可以划分为三个部分:对象头(Header)、实例数据(Instance Data)和对齐填充(Padding)
  • 对象头包括:对象自身的运行时数据(Mark Word),所属类类指针,数组长度(如果是数组对象)

对象的访问定位
  • Java程序会通过栈上的reference数据来操作堆上的具体对象。
  • 对象访问方式也是由虚拟机实现而定的,主流的访问方式主要有使用句柄和直接指针两种
垃圾收集(GC) 对象的死亡 引用计数法
  • 在对象中添加一个引用计数器,每当有一个地方引用它时,计数器值就加一;当引用失效时,计数器值就减一;任何时刻计数器为零的对象就是不可能再被使用的。
  • 互相循环引用的对象无法被回收

可达性分析法
  • 通过一系列称为“GC Roots”的根对象作为起始节点集,从这些节点开始,根据引用关系向下搜索,搜索过程所走过的路径称为“引用链”(Reference Chain),如果某个对象到GC Roots间没有任何引用链相连,或者用图论的话来说就是从GC Roots到这个对象不可达时,则证明此对象是不可能再被使用的

  • 可作为GC Roots的对象:
  1. 虚拟机栈(栈帧中的本地变量表)中引用的对象
  2. 在方法区中类静态属性引用的对象
  3. 方法区中常量引用的对象
  4. 在本地方法栈中JNI(即通常所说的Native方法)引用的对象
  5. Java虚拟机内部的引用,如基本数据类型对应的Class对象,一些常驻的异常对象(比如NullPointExcepiton、OutOfMemoryError)等,还有系统类加载器
  6. 所有被同步锁(synchronized关键字)持有的对象
  7. 反映Java虚拟机内部情况的JMXBean、JVMTI中注册的回调、本地代码缓存等
四种引用
  • 强引用(Strongly Re-ference):无论任何情况下,只要强引用关系还存在,垃圾收集器就永远不会回收掉被引用的对象
  • 软引用(Soft Reference):只被软引用关联着的对象,在系统将要发生内存溢出异常前,会把这些对象列进回收范围之中进行第二次回收,如果这次回收还没有足够的内存,才会抛出内存溢出异常
  • 弱引用(Weak Reference):当垃圾收集器开始工作,无论当前内存是否足够,都会回收掉只被弱引用关联的对象
    Reference):只被软引用关联着的对象,在系统将要发生内存溢出异常前,会把这些对象列进回收范围之中进行第二次回收,如果这次回收还没有足够的内存,才会抛出内存溢出异常
  • 弱引用(Weak Reference):当垃圾收集器开始工作,无论当前内存是否足够,都会回收掉只被弱引用关联的对象
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/667337.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号