1、 运行时数据区域
  1) 程序计数器
    | 线程私有,存储线程运行时所执行字节码的行号,实现分支、循环、跳转、异常处理、线程恢复等基础功能
    | Java方法,记录正在执行的虚拟机字节码指令的行号;Native方法计数器值为空(Undefined)
    | 唯一一个没有OutOfMemoryError情况的区域
  2) Java虚拟机栈
    | 线程私有,和线程生命周期相同。描述Java方法执行的内存模型:每个方法执行的同时会产生一个栈帧,存储局部变量表、操作数栈、动态链接、方法出口等。
    | 每个方法从调用到执行完成的过程,就对应一个栈帧在虚拟机栈中入栈到出栈的过程
    | 常说的堆内存、栈内存指的是栈中的局部变量表
    | 局部变量表中存储的是编译期可知的各种基本数据类型、对象引用类型(不等同于对象本色)和returnAddress类型(指向了一条字节码指令的地址)
    | 局部变量表在编译期间完成分配,方法运行期间不会改变局部变量表的大小
    | 线程请求的栈深度大于虚拟机所运行的深度,抛出StackOverflowError异常;如果虚拟机栈可以动态扩展,扩展时无法申请到足够内存,抛出OutOfMemoryError异常
  3) 本地方法栈
    | 与虚拟机栈所发挥的作用相似,执行的是虚拟机使用到的Native方法服务。
    | HotSpot虚拟机把本地方法栈和虚拟机栈合二为一
  4) 堆
    | 线程共享,内存中最大的一块,虚拟机启动时创建,几乎所有的对象和数组都要在堆上分配
    | Java堆是垃圾收集器管理的主要区域,可细分为:新生代(Eden空间、From Survivor空间、To Survivor空间),老年代,线程私有的分配缓存区(TLAB)
    | 无论哪个区域,存储的都仍然是对象实例
    | 没有内存完成实例分配,并且堆也无法再扩展时,将会抛出OutOfMemoryError异常
  5) 方法区
    | 线程共享,存储加载的类信息、常量、静态变量、即时编译器编译后的代码,别名Non-Heap(非堆)
    | HotSpot1.7之前也称为"永久代"(Permanent Generation)(会受到-XX:MaxPermSize的限制),1.8之后采用元数据区代替
    | 回收空间主要针对类的卸载和常量池的回收
    | 当方法区无法满足内存分配需求时,将抛出OutOfMemoryError异常
  6) 运行时常量池
    | 方法区的一部分
    | Class文件中除了有类的版本、字段、方法、接口等描述信息外,还有一项信息是常量池,存放编译期生成的各种字面量和符号引用。这部分内容将在类加载后进入方法区的运行时常量池中存放
    | 运行期间也可能将新的常量放入池中,如String类的intern()方法
    | 当常量池无法再申请到内存时会抛出OutOfMemoryError异常
  7) 直接内存
    | 并不是虚拟机运行时数据区的一部分,也不是Java虚拟机规范中定义的内存区域。
    | JDK1.4中新加入NIO(New Input/Output)类,基于通道(Channel)与缓冲区(Buffer)的I/O方式,可以使用Native函数库直接分配堆外内存,然后通过一个存储在Java堆中的DirectByteBuffer对象作为这块内存的引用操作

2、 Java虚拟机对象
  1) 对象的创建
    | 遇到一条new指令时,首先检查new指令的参数是否能在常量池中定位到一个类的符号引用,并且检查该类是否已经被加载、解析和初始化过
    | 检查通过后,虚拟机将为新生对象分配内存。对象所需内存在类加载完成后便可完全确认。(指针碰撞、空闲列表、CAS、TLAB)
    | 内存分配完成后,虚拟机需要将分配到的内存空间都初始化为零值(不包括对象头)
    | 虚拟机对对象进行必要的设置,例如:对象是哪个类的实例、如何能找到类的元数据信息、对象的哈希码、对象的GC分代年龄等信息,这些信息存放在对象头之中。
    | 一般来说(由字节码中是否跟随invokespecial指令所决定),执行new指令之后会接着执行<init>方法,对象会被完全生产出来
  2) 对象的内存布局
    对象头:
      | 自身的运行时数据:
        哈希码,GC分代年龄,锁状态标志,线程持有的锁,偏向线程ID,偏向时间戳。32位和64位虚拟机长度分别为32bit和64bit,官称“Mark Word”
      | 类型指针:
        对象指向他的类元数据的指针,虚拟机通过这个指针来确定这个对象是哪个类的实例(并不是所有的虚拟机实现都必须在对象数据上保留类型指针)
        如果对象是Java数组,那在对象头中还必须有一块用于记录数组长度的数据
    实例数据部分:
      对象真正存储的有效信息,各种类型的字段(包括父类继承和子类定义)
      存储顺序受到虚拟机分配策略参数和字段在Java源码中定义的顺序的影响
    对齐填充:
      不是必然存在,HotSpot VM的自动内存管理系统要求对象起始地址必须是8字节的整倍数,通过对齐填充来补全。
  3) 对象访问定位
    | 句柄访问:
      Java栈本地变量表中reference中存储的就是对象的句柄地址,句柄中包括了对象实例数据与类型数据各自的具体地址信息。Java堆中将会划分出一块内存作为句柄池
      好处是reference中存储的是稳定的句柄地址,在对象被移动时(垃圾收集移动对象是非常普遍的行为)只会改变句柄中的实例数据指针,而reference本身不需要修改
    | 直接指针访问
      Java堆对象的布局中需要放置访问类型数据的相关信息,reference存储的直接就是对象地址
      好处是速度更快,节省了一次指针定位的时间开销。HotSpot使用此种方式

【JVM学习笔记一】Java内存区域的更多相关文章

  1. 【转载】Java系列笔记(3) - Java 内存区域和GC机制

    Java系列笔记(3) - Java 内存区域和GC机制 转载:原文地址http://www.cnblogs.com/zhguang/p/3257367.html 目录 Java垃圾回收概况 Java ...

  2. JVM学习笔记:Java运行时数据区域

    JVM执行Java程序的过程中,会使用到各种数据区域,这些区域有各自的用途.创建和销毁时间.根据<Java虚拟机规范>,JVM包括下列几个运行时数据区域,如下图所示: 其中红色部分是线程私 ...

  3. JVM笔记(一) Java内存区域

    Java 内存区域 总概 java虚拟机在执行java程序的过程中,会把它管理的内存划分为几个不同的数据区域.每当运行一个java程序时,就会启动一个虚拟机. 具体的区域如图所示: 同时,方法区 与 ...

  4. Java系列笔记(3) - Java 内存区域和GC机制

    目录 Java垃圾回收概况 Java内存区域 Java对象的访问方式 Java内存分配机制 Java GC机制 垃圾收集器 Java垃圾回收概况 Java GC(Garbage Collection, ...

  5. JVM系列1:Java内存区域

    JVM系列主要分享自己都虚拟机的理解,我自学时的知识框架多来源于<深入理解Java虚拟机_JVM高级特性与最佳实践>这本书,感兴趣的朋友可直接去阅读这本书. 本系列暂定有3部分,它们是学习 ...

  6. 深入理解JAVA虚拟机阅读笔记1——JAVA内存区域

    一.Java内存区域 1.程序计数器 线程私有. 当前线程所执行的字节码的行号指示器.由于JAVA是多线程的,因此每个线程都独立的程序计数器. 异常:没有规定任何OutOfMemeryError情况的 ...

  7. JVM学习笔记(一):Java虚拟机和虚拟机内存区域

    为什么Java程序需要运行在虚拟机上 因为Java在设计之初的跨平台特性,我们知道Java程序是运行在Java虚拟机上的.如果你要问为什么Java程序要运行在虚拟机上,我可以反问你几个问题. 为什么买 ...

  8. 《深入java虚拟机》读书笔记之Java内存区域

    前言 该读书笔记用于记录在学习<深入理解Java虚拟机--JVM高级特性与最佳实践>一书中的一些重要知识点,对其中的部分内容进行归纳,主要是方便之后进行复习. 运行时数据区域 Java虚拟 ...

  9. JVM系列一(Java内存区域和对象创建).

    一.JVM 内存区域 堆 - Heap 线程共享,JVM中最大的一块内存,此内存的唯一目的就是存放对象实例,Java 堆是垃圾收集器管理的主要区域,因此很多时候也被称为"GC堆"( ...

  10. JVM虚拟机(三):Java内存区域

    运行时数据区   Java虚拟机再执行Java程序过程中会把它所管理的内存划分为若干个不同分工的数据区域. 程序计数器   程序计数器时一块较小的内存空间,它可以看作是当前线程所执行的字节码的行号指示 ...

随机推荐

  1. Java多线程编程核心技术-第5章-定时器 Timer-读书笔记

    第 5 章 定时器 Timer 定时 / 计划功能在移动开发领域使用较多,比如 Android 技术.定时计划任务功能在 Java 中主要使用的就是 Timer 对象,他在内部使用多线程的方式进行处理 ...

  2. 《always run团队》第六次作业:团队项目系统设计改进与详细设计

    项目 内容 这个作业属于哪个课程 老师链接 这个作业的要求在哪里 作业链接地址 团队名称 always run 作业学习目标 掌握面向对象软件设计方法:(2)完善系统设计说明书,掌握面向对象详细设计内 ...

  3. apache在linux下安装

    yum安装 主流Linux系统版本基本上都集成了apache服务器httpd,我们可以通过如下命令来查看我们的操作系统上是否已经安装了apache服务器httpd rpm -qa | grep htt ...

  4. String s = new String("xyz");创建了几个String Object?并作说明。

    String s = new String("xyz");创建了几个String Object?并作说明. 共产生了两个2个对象,第一个是字符串常量xyz,存储于常量池中.第二个对 ...

  5. 06-C#笔记-常量

    1. 进制 前缀:0x 或 0X 表示十六进制,0 表示八进制,没有前缀则表示十进制. 后缀:可以是 U 或 L 的组合,其中,U 和 L 分别表示 unsigned 和 long.后缀可以是大写或者 ...

  6. maven jar包冲突的发现与解决[工具篇]

    本文是我的第177篇文章. 关于jar冲突排查解决的问题,相信很多小伙伴也都知道有一些,无非就是两类:命令 or 工具. 命令方式比如: mvn dependency:tree 工具方式比如: Mav ...

  7. 学好Python后可从事岗位+学习Python的难度

    一.学好Python好就业: 1.Linux运维.Linux运维是必须而且一定要掌握Python语言,Python可以满足Linux运维工程师的工作需求提升效率,总而提升自己的能力.用Python实现 ...

  8. 复旦大学2018--2019学年第二学期(18级)高等代数II期末考试第六大题解答

    六.(本题10分)  设 $A$ 为 $n$ 阶实对称阵, 证明: $A$ 有 $n$ 个不同的特征值当且仅当对 $A$ 的任一特征值 $\lambda_0$ 及对应的特征向量 $\alpha$, 矩 ...

  9. 在eclipse中新建java问题报错:The type XXX cannot be resolved. It is indirectly referenced from required .class files

    在Eclipse中遇到The type XXX cannot be resolved. It is indirectly referenced from required .class files错误 ...

  10. 详细讲解redis数据结构(内存模型)以及常用命令

    Redis数据类型 与Memcached仅支持简单的key-value结构的数据记录不同,Redis支持的数据类型要丰富得多,常用的数据类型主要有五种:String.List.Hash.Set和Sor ...