一、运行时数据区

程序计数器(线程私有)

1.程序计数器占用jvm内存较小,主要用来记录当前线程所执行的字节码的位置,因为jvm的多线程都是通过cpu对线程进行来回切换,所以在某个确定的时间cpu只会执行一个线程,为了频繁的线程切换后各线程都能找到自己之前执行的准确位置,所以每条线程都维护了一个独立的程序计数器,互不干扰;

2.该区域是java虚拟机规范中唯一一个没有规定任何oom的内存区域

虚拟机栈(线程私有)

1.每个线程都会创建一个虚拟机栈,标识java方法执行的内存模型,每个方法执行的时候虚拟机都会为其生成一个栈帧,用来存储局部变量表、操作数栈、动态链接、方法出口等信息;每个方法被调用到其执行完毕的过程就对应一个栈帧从入栈到出栈的过程。虚拟机栈的生命周期和线程是相同的

2.虚拟机栈是一个先进后出的,栈顶的栈帧称为当前栈帧,虚拟机只会操作处于栈顶的栈帧

3.局部变量表

局部变量表用于记录执行该方法时会使用到的变量值,其主要存放了编译期可知的各种java基本数据类型,对象的引用以及return adress(指向了一条字节码引用的地址),

本地方法栈

与虚拟机栈作用相似,其执行的是本地方法而不是java方法

堆(线程共享)

用于存储对象实例,可固定大小,也可动态扩展,通过-Xmx和-Xms来设置堆分配到内存的最大值和初始值

方法区(线程共享)

用于存储已被虚拟机加载的类型信息,常量,静态变量,及时编译器编译后的代码缓存等数据

二、对象的创建

新对象的内存分配

当new一个新的对象时,通常有两种方式为新对象分配内存空间,一种是指针碰撞法,该方法使用的前提是堆内存是规整的,所有已用的内存在一边,没被使用的内存在另一边,中间放一个指针作为分界点的标记,当需要为一个新对象分配内存时,只需将指针向没被使用的内存那侧移动对应的距离即可;另一种方式是空闲列表,当堆内存不规整且已用和未用内存混乱交错时使用,需要虚拟机维护一个列表来记录哪些内存是可用的,当需要为一个新对象分配内存时,从列表里找到对应的空间分配给该对象,然后更新列表上的记录;

堆内存是否规整则需要根据其使用的垃圾收集器是否有压缩整理的能力而决定,像Serial,ParNew等带压缩整理过程的收集器采用的内存分配算法就是指针碰撞;像CMS这种基于清楚算法的收集器理论上只能采用空闲列表的方法(为什么是理论上详见深入理解JVM虚拟机 第三版 P48);

如何在并发下保证内存分配的线程安全

由于内存分配的频繁性,当需要给对象A分配内存,指针还没移动B对象进来了且使用了原本要给A用的那块内存,所以会存在安全隐患,解决这类并发下内存分配的安全问题有如下两种方法

-对分配内存的动作做同步处理,实际上虚拟机是采用CAS配上失败重试的方式保证更新操作的原子性

-TLAB(分配缓冲)将分配内存的操作按照线程划分在不同空间,即每个线程在堆中预先分配一小块内存,当哪个线程要分配内存时就去其自己线程所在的缓冲区分配,这样各线程互不干扰,确保了并发下的安全性;只有当线程的本地缓冲区用完了分配新的缓冲区时才需要同步锁定,可以通过-XX:+/-UseTLAB命令来开启/关闭是否启用缓冲区

三、对象的构成

对象在堆中的存储布局主要有以下三个部分:

1.对象头(大小刚好是8的整数倍)

对象头包含两类信息,一类用于存储对象自身的运行时数据,如哈希码,GC分代年龄,锁状态标志,线程持有的锁,偏向线程ID,偏向时间戳等;另一类是类型指针,即对象指向它的类型元数据的指针,java虚拟机通过这个指针来确定该对象是那个类的实例;

2.实例数据

实例数据是对象存储的有效信息,也就是代码里定义的各种类型的字段内容,无论是父类继承的还是子类中定义的字段都必须记录起来

3.对齐填充

HotSpot虚拟机的自动内存管理系统要求对象起始地址必须是8字节的整数倍,因为对象头已被设计成刚好是8的整数倍,所以当实例数据没有与8的整数倍对齐时,需要对其填充

四、对象的访问定位

1.句柄访问

堆中划分一块内存作为句柄池,里面包含了对象的实例数据指针和类型数据指针,该指针指向堆或方法区中各自具体的地址信息,而栈中的本地变量表中的对象的引用指向堆中的句柄池,这样对象寻址的时候由栈中的引用首先找到句柄池中该对象的指针,再去找具体的存储地址;

2.直接指针访问

栈中的本地变量表中的引用直接指向堆中对象的地址,但是对象在堆中的布局就必须考虑如何放置对象类型数据的相关信息;

jvm之自动内存管理的更多相关文章

  1. JVM介绍&自动内存管理机制

    1.介绍JVM(Java Virtual Machine,Java虚拟机) JVM是Java Virtual Machine的缩写,通常成为java虚拟机,作为Java可以进行一次编写,到处执行(Wr ...

  2. 深入理解JVM(一) -- 自动内存管理机制

    Java运行时数据区域分为:程序计数器,虚拟机栈,本地方法栈,Java堆,方法区,运行时常量池,直接内存,结构如下: 1.程序计数器: 是一块较小的内存空间,可以看作是当前线程所执行的字节码的行号指示 ...

  3. JVM探索之——内存管理(一)

    本系列的第一篇文章,预计本系列最后面会有两三个案例. Java与C.C++不一样Java不需要Coder进行手动内存管理,而这一切都交给JVM进行自动内存管理,这从某种程度上来说也减轻了我们Coder ...

  4. JVM自动内存管理学习笔记

    对于使用 C.C++ 的程序员来说,在内存管理领域,他们既是拥有最高权力的皇帝又是从事最基础工作的劳动人民——拥有每一个对象的“所有权”,又担负着每一个对象生命开始到终结的维护责任.对于 Java 程 ...

  5. JVM自动内存管理-Java内存区域与内存溢出异常

    摘要: JVM内存的划分,导致内存溢出异常的可能区域. 1. JVM运行时内存区域 JVM在执行Java程序的过程中会把它所管理的内存划分为以下几个区域: 1.1 程序计数器 程序计数器是一块较小的内 ...

  6. JVM自动内存管理机制——Java内存区域(下)

    一.虚拟机参数配置 在上一篇<Java自动内存管理机制——Java内存区域(上)>中介绍了有关的基础知识,这一篇主要是通过一些示例来了解有关虚拟机参数的配置. 1.Java堆参数设置 a) ...

  7. JVM自动内存管理机制——Java内存区域(上)

    一.JVM运行时数据区域概述 Java相比较于C/C++的一个特点就是,在虚拟机自动内存管理机制的帮助下,我们不需要为每一个操作都写像C/C++一样的delete/free代码,所以也不容易出现内存泄 ...

  8. JVM自动内存管理机制--读这篇就GO了

    之前看过JVM的相关知识,当时没有留下任何学习成果物,有些遗憾.这次重新复习了下,并通过博客来做下笔记(只能记录一部分,因为写博客真的很花时间),也给其他同行一些知识分享. Java自动内存管理机制包 ...

  9. JVM | 第1部分:自动内存管理与性能调优《深入理解 Java 虚拟机》

    目录 前言 1. 自动内存管理 1.1 JVM运行时数据区 1.2 Java 内存结构 1.3 HotSpot 虚拟机创建对象 1.4 HotSpot 虚拟机的对象内存布局 1.5 访问对象 2. 垃 ...

随机推荐

  1. 分布式版本控制系统Git的使用;

    1.什么是Git Git是一个分布式的版本控制软件: 软件,类似于qq.office等安装到电脑才能使用的工具. 版本控制,类似于毕业论文,视频剪辑等需要反复修改和保留原历史数据: 分布式 文件夹拷贝 ...

  2. Atcoder Beginner Contest 200 E. Minflip Summation(概率数论)

    题面 一个字符串 T T T 是由一个包含 0.1.? 的字符串 S S S 循环连接 K K K 次获得的. 字符串 T T T 中的每个 ? 都可以换成 0 或 1 ,假设 T T T 中一共有 ...

  3. java方法---可变参数

    可变参数 在方法的声明中,在指定参数类型后面加一个...(省略号) 一个方法中只能指定一个可变参数,它必须是方法的最后一个参数,任何普通参数必须在它之前声明:

  4. 【JDBC】学习路径10-c3p0数据源的使用(JDBC完结)

    第一章:下载 c3p0官网:https://www.mchange.com/projects/c3p0/ 这个是SourceForge提供的下载地址:https://sourceforge.net/p ...

  5. C与C++有什么区别

    C是一个结构化语言,它的侧重点在于算法和数据结构.对语言本身而言,C是C++的一个子集. C程序的设计首要考虑的是如何通过一个过程,对输入进行运算处理,得到输出. 对于C++,首要考虑的是如何构造一个 ...

  6. volatile 函数影响子查询提升

    我们知道 volatile 函数会影响SQL的执行性能,比如:volatile 类型函数无法建函数索引.volatile 函数针对每条记录都要执行一次.本篇的例子主要讲述 volatile 类型的函数 ...

  7. 华南理工大学 Python第3章课后小测-2

    1.(单选)给出如下代码 s = 'Hello scut' print(s[4::-1]) 上述代码的输出结果是(本题分数:2)A) HelloB) olleHC) scutD) tucs您的答案:B ...

  8. Netty 学习(三):通信协议和编解码

    Netty 学习(三):通信协议和编解码 作者: Grey 原文地址: 博客园:Netty 学习(三):通信协议和编解码 CSDN:Netty 学习(三):通信协议和编解码 无论使用 Netty 还是 ...

  9. 【译】CLR类型加载器设计

    前言 本文翻译自BotR中的一篇,原文链接 Type Loader Design ,可以帮助我们了解CLR的类型加载机制(注意是Type类型,而不是Class类),文中涉及到术语或者容易混淆的地方,我 ...

  10. Echarts中tooltip解决显示指定数据

    今天开发中遇到一个问题,echarts图表触摸x轴触发tooltip会将x轴上所有的数据展示出来,但是有些场合只需要展示某些数据就可以,并不需要全部展示,如下图: 这里警戒线因为需要开关,所以使用填充 ...