1.java堆中对象的创建,布局,访问
Java对象的内存表示模型是Oop-Klass模型。
1.1 对象的创建
①虚拟机在碰到一条new指令时,会检查这个指令参数(是一个符号引用,对应一个类)是否能在运行时常量池中定位到一个类,并且检查这个类是否被加载,解析和初始化.
②在类加载检查通过后,虚拟机需要为对象分配内存.对象所需内存的大小,在类加载完成后完全确定.这里涉及到对象内存分配的方法:指针碰撞和空闲列表.
指针碰撞:如果堆内存空间是绝对规整的,在已分配堆内存和未分配堆内存之间有一个指针作为分界点的指示器.在为新对象分配堆内存时,只需要将指针移动新对象大小的位置即可.
空闲列表:如果堆内存时不规整的,已分配的堆内存和未分配的堆内存犬牙交错,那么就必须维护一个内存列表,列表中记录了哪些堆内存已使用,哪些堆内存未使用,在为新对象分配堆内存时,选择一块较大的未使用的堆内存区域分配给对象,并更新列表记录.
注意:
在对象创建过程中,无论采用哪种方式,都有一个线程安全问题(如采用指针碰撞,线程A,B同时取到指针,分配对象会出现同时争用一块堆内存的情况).
如何解决这个问题呢?
一是在内存分配时候进行同步处理,使用CAS(Compare-And-Swap,比较并交换)保证原子性+失败重试的方式进行分配.
二是使用TLAB(Thread Local Allocation Buffer,线程本地分配缓存),就是每个线程在创建的时候,预先在Java堆中分配一小块内存区域,作为自己的TLAB,当线程需要分配对象堆内存时候,就在当前线程的TLAB上分配即可.
在虚拟机中,可以使用-XX:+/-UseTLAB虚拟机参数开启或者关闭使用TLAB.
③对象实例属性初始化为默认值,如int类型默认为0,引用的对象默认为null
④设置对象头(Object Header,对象头包含两部分:Mark Word,klass pointer)
⑤调用构造函数进行初始化,执行<init>方法.
1.2 对象在堆内存中的布局
1.2.1一个对象在堆内存中的布局包含两个部分:对象头(Header),实例数据(Instance Data).zzm书上把对齐补充也归为一部分,我觉得不妥.因为对齐补充是一种方式,而不属于内容.
①对象头(Header):对象头包含两部分内容,一部分内容是Mark Word,一部分是类型指针.
Mark Word:用于存储对象自身的运行时数据,包括对象的哈希码值,GC分代年龄,锁状态标志,偏向线程id,偏向时间戳等.见图片附件.
元数据指针(也叫类型指针,Klass Pointer):指向对象所属类元数据的指针,虚拟机通过这个指针确定对象是哪个类的实例.(不是全部虚拟机都是这么实现的,访问对象所属类信息,并不需要对象本身,见对象访问定位,可以通过栈帧的局部变量表)
注意:
如果对象是数组,对象头中还要增加一块记录数组长度的数据.
②实例数据:实例对象中包含的属性字段变量内容,包含从父类继承的.属性字段根据分配策略,相同大小的字段分配在一起,例如long/double都是64位,分配在一起.
③对齐补充:对齐补充只是一种字节补齐方式.HotSpot虚拟机的自动内存管理系统要求对象的大小必须是8字节的整数倍,不够整数倍的需要使用占位符对齐补充.
1.2.2 对象所占字节大小计算
①在32位虚拟机中,MarkWord占32bit,为4个字节;在未开启指针压缩的情况下,类型指针(Klass Pointer)占32位,为4个字节.对象头共为8个字节.
在开启指针压缩的情况下,只影响类型指针所占字节大小,为2个字节,这时,对象头是6个字节.
②在64位虚拟机中,MarkWord占64bit,为8个字节;在未开启指针压缩的情况下,类型指针(Klass Pointer)占64位,为8个字节.对象头共为16个字节.
在开启指针压缩的情况下,只影响类型指针所占字节大小,为4个字节,这时,对象头是12个字节.
③属性字段数据大小
基本数据类型:boolean、byte占用1个字节,char、short占用2个字节,int、float占用4个字节,long、double占用8个字节.
引用类型:每个引用类型占用4个字节
数组大小:特殊的地方,数组长度占用4个字节保存,其余同普通对象.
1.3 对象的访问定位
当程序要访问一个对象时,是通过栈帧的局部变量表中对象的引用类型(reference)操作的.在虚拟机规范中,只规定了reference类型需要指向具体的对象,但没有规定如何定位.
目前主流的访问方式有两种:句柄和直接指针.
句柄:如果使用句柄访问对象,那么在堆内存中需要划分出一块区域作为句柄池,reference类型指向的是句柄池中的句柄(引用类型中存放的是句柄的地址).在句柄中包含两部分,
一部分是指向对象实例数据的指针(对象实例数据在堆内存中),一部分是指向对象所属类的指针(对像所属类的指针指向的是方法区中的类信息).
直接指针:顾名思义,直接指针就是在栈帧的局部变量表中的reference类型直接指向了对象(引用类型中存放的是对象的地址).存储对象的堆内存包含对象实例数据和到对象所属类的指针(指向方法区的类信息).
对比:
句柄:使用句柄的优点就是稳定,当对象移动的时候,不需要改变引用类型指向的句柄地址.
直接指针:使用直接指针的优点就是速度快,省去了一次定位成本,目前HotSpot采用此方式.
相关推荐
Java堆是JVM内存管理中最大的一块区域,它负责存储对象实例及数组值。在虚拟机启动时创建,并且被所有线程共享。堆是垃圾收集器管理的主要区域,其大小可以通过-Xms和-Xmx参数进行控制。在JDK 1.2版本之后,Java堆被...
内存管理是 JVM 中最重要的组件之一,它负责为对象分配内存和释放内存。垃圾回收(Garbage Collector,GC)是内存管理的主要组件,它负责回收堆中不再使用的对象,以释放内存。垃圾回收有两种方式:Minor 收集和 ...
一、JVM内存结构 1. **程序计数器(Program Counter Register)**:每个线程都有一个独立的程序计数器,用于存储当前线程所执行的字节码指令地址。 2. **虚拟机栈(Java Stack)**:存储方法的局部变量、操作数栈...
### JVM内存管理与GC模型详解 #### 一、引言 在现代软件开发中,Java虚拟机(JVM)作为一种广泛使用的平台,其内部机制尤其是内存管理和垃圾收集(GC)模型,对提升程序性能和稳定性至关重要。本文将深入探讨Sun ...
当-Xms与-Xmx相同时,JVM在启动时会分配一个固定大小的堆内存,从而避免了动态调整带来的性能开销。 - **示例**:`java -Xms3550m ...` #### 2. -Xmx(Maximum Heap Size) - **定义**:设置JVM可以使用的最大堆...
在探讨JVM内存管理之前,我们先来看一下为何要深入了解这一主题。对于深入掌握Java的人来说,内存管理是不可或缺的一部分。随着技术的发展,内存管理变得越来越自动化,但这也意味着我们需要更加了解其背后的机制...
#### 一、JVM内存模型概览 JVM(Java虚拟机)内存模型主要由以下几个部分组成:程序计数器、Java虚拟机栈、本地方法栈、Java堆以及方法区(在JDK 8之后称为元空间)。下面将对这几个部分进行详细介绍。 #### 二、...
JVM内存调优是一个复杂的过程,需要根据应用程序的特性和资源需求进行调整。通常,我们需要关注垃圾收集器的性能,如新生代与老年代的占比,以及内存分配和回收的效率。同时,监控系统的CPU使用率、内存占用和GC日志...
### Sun JVM原理与内存管理 #### 一、Sun JDK 1.6 GC (Garbage Collector) Sun JDK 1.6 的垃圾收集器(GC)是其内存管理的关键组成部分,它负责自动地回收不再使用的对象所占用的内存。本文将详细介绍Sun JDK 1.6 GC...
#### 一、理解JVM内存模型 在进行JVM内存配置优化之前,我们需要了解Java虚拟机(JVM)的内存结构。Java的逻辑内存模型大致分为几个部分: 1. **堆内存(Heap)**:主要用于存储对象实例、数组等引用类型的数据。在...
总之,MAT作为一款强大的JVM内存分析工具,对于优化Java应用的内存使用,提升应用性能,尤其是对于Mac OS X平台的开发者来说,是不可或缺的利器。通过熟练掌握MAT的使用,开发者可以更有效地管理和优化应用程序的...
解决内存溢出的方法有两种:一是优化程序代码,减少全局变量的引用,让程序使用完变量的时候释放该引用,能够让垃圾回收器回收,释放资源;二是物理解决,增大物理内存,然后通过调整 JVM 的参数来调整内存的大小。 ...
Java虚拟机(JVM)是Java程序运行的基础,它负责管理程序的内存,包括对象的创建、垃圾收集以及内存分配。在"jvm内存分析-jdk17-memoryAnalyzer"这个主题中,我们将深入探讨JVM内存结构,特别是针对Java 17版本的...
5. **内存调优**:根据应用需求调整JVM内存设置,如-Xms, -Xmx控制堆内存大小,-XX:MetaspaceSize, -XX:MaxMetaspaceSize设定方法区大小。 6. **使用G1垃圾收集器**:G1能平衡吞吐量和响应时间,且支持并行和并发...
`jmap`是Java的一个命令行工具,用于获取堆内存的详细信息,包括堆dump,这对于分析JVM内存状态非常有用。 本文将深入探讨JVM内存结构、`jmap`工具的使用以及如何分析`dump.txt`文件中的内存日志。 1. JVM内存结构...
本文将围绕JVM性能调优这一主题展开,重点探讨JVM内存管理机制、垃圾回收(GC)算法及其优化策略。 #### Java参数传递机制解析 首先,澄清Java中的参数传递机制是非常重要的,这有助于我们更好地理解对象在方法调用...
JVM内存管理主要包括内存结构、内存分配以及垃圾回收(GC)等方面。了解这些知识对于优化Java应用程序的性能至关重要。 ### 1. JVM内存结构 #### 1.1.1 JVM内存概述 JVM内存分为几个关键区域,每个区域都有特定的...
堆被分为新生代(Young Generation)和老年代(Old Generation),新生代又分为Eden区、Survivor区(通常两个),用于对象的生命周期管理。 - **栈内存**:每个线程都有自己的程序计数器、虚拟机栈和本地方法栈。栈...
**JVM内存管理及调优** Java虚拟机(JVM)是Java程序运行的基础,它为Java应用程序提供了运行环境。JVM内存管理是优化Java应用性能的关键环节,涉及到内存分配、垃圾回收以及内存溢出等问题。毕玄,一位在淘宝有着...