JVM之对象
几乎所有对象都是在堆中分配内存的,这次来讲讲java的对象。
对象的创建主要分为以下几步:
首先,查看类是否装载。当JVM读取到new指令的时候,会拿着符号描述去方法区寻找它所属的类,如果未查找到,则需要先对类进行加载解析初始化;
然后,为对象分配空间。主要涉及两种方式,第一种是指针碰撞法,顾名思义,两个指针挪动,为新来的对象“挪”空间,前提是配合相应的GC算法使堆空间时刻保持连续,同时,如果是多线程还需要考虑同步问题,可以使用CAS或TLAB的方式;第二种是空闲列表法,如果堆空间不连续的话可以采用此方法,每次GC之后把可利用的空间写入到一个列表,通过维护这个列表来得知在哪里给对象分配内存。
分配完内存之后,需要给对象的属性设置零值(不包含对象头的区域),即初始值,如果此时访问对象属性的话得到的将是一个零值。
接下来设置对象头信息,包括对象哈希码,类的地址,对象的GC年龄分代信息,锁状态等。
最后一步就是执行<init>方法,为对象赋值。
对象的大小
对于一个新建的无任何属性的空的Object对象,它的大小为8byte,它的引用变量前面说过,为4byte,因此创建一个空的Object对象需要占用内存12byte;如果建立一个有属性的对象需要多大空间呢?我们来分析一下
class hello{
int a;
boolean b;
Object c;
}
如果要创建这样一个对象,我们知道所有的类都需要继承Object类的,因此首先需要一个8byte的空壳对象,然后int属性占4byte,boolean属性占1byte,引用变量属性占4byte(注意c仅仅是一个引用),占用17字节,而JVM规定,对象空间占用必须为8byte的整数倍,因此需要凑整,也就是这个对象在堆中需要占用24字节大小。
这里还要说一下基本类型的包装类型的对象大小,对于这类对象,即使声明一个空对象,也至少要占用内存为12byte,这还只是个空对象,而且还要凑整,所以需要16字节,这已经是基本类型的2倍以上了,因此我们平时尽量不要使用包装类型的对象,当然,jdk5之后JVM会自动拆箱装箱,对包装类型的内存占用空间也有了一定的优化。
对象头
因为之前在学习锁优化的时候提到了Mark Word,所以这次又着重看了一下这里。对象头是一个无固定格式的,包含对象信息的一段序列。对象头的信息主要分两部分存放
第一块用来存储运行时所需要的信息,叫Mark Word,用来存放如哈希码,GC年龄分代,锁状态标志,偏向线程ID等,对于32位和64位系统,在未开启压缩指针下这部分分别为固定大小32位和64位。在未加锁32位系统下,MarkWord中有25位用来存放对象的哈希码,4bit存放对象的年龄分代信息,2bit存放锁标识位,1bit固定为0;
第二块是一个指向它所属的类的一个类型指针。
对于普通对象,JVM可以通过这个指针很轻易的找到它所属的类信息以及对象大小,但是如果是一个数组对象,通过前面所说的信息还是无法确定这个数组的大小,甚至追溯到数组对象的元数据,因此,对于数组对象,对象头信息还需要一条记录数组长度的数据。
对象的访问定位
如果想通过栈上的reference数据来访问操作对象,有两种方式,第一种是直接指针访问,这是Hotpot使用的访问方式,在引用类型中直接记录下对象的地址,速度快,但是如果频繁GC导致对象在堆中的位置频繁移动,那么该地址每次都需要修改,可能会带来一些性能问题;第二种是句柄访问,即在堆区划分出来一块内存来作为句柄池,栈中的引用类型记录对象的句柄地址,句柄地址中记录对象的实际位置,这样每次移动对象只需要维护句柄池即可,栈区无需修改,相对会稳定一些。总之,两种方式各有优点。
JVM之对象的更多相关文章
- JVM中对象的创建过程
		JVM中对象的创建过程如以下流程图中所示: 对其主要步骤进行详细阐述: 为新生对象分配内存: 内存的分配方式: 指针碰撞:假设Java堆中内存是绝对规整的,所有用过的内存放在一边,空闲的内存在另一边, ... 
- JVM中对象的回收过程
		当我们的程序开启运行之后就,就会在我们的java堆中不断的产生新的对象,而这是需要占用我们的存储空间的,因为创建一个新的对象需要分配对应的内存空间,显然我的内存空间是固定有限的,所以我们需要对没有 ... 
- Java虚拟机笔记(五):JVM中对象的分代
		为什么要分代 为什么需要把堆分代?不分代不能完成他所做的事情么?其实不分代完全可以,分代的唯一理由就是优化GC性能.你先想想,如果没有分代,那我们所有的对象都在一块,GC的时候我们要找到哪些对象没用, ... 
- jvm回收对象
		jvm在判断对象死亡之前需要判断对象是否可到达,方法有引用计数算法和可达性分析算法,jvm采用的是后者.首先来了解一下这两种算法. 引用计数算法: 算法定义 为每个对象增加一个字段记录被引用的次数,并 ... 
- JVM——深入分析对象的内存布局
		概述 一个对象本身的内在结构需要一种描述方式,这个描述信息是以字节码的方法存储在方法区中的.Class本身就是一个对象,都以KB为单位,如果new Integer()为了表示一个数据就占用KB级别的内 ... 
- JVM与对象初始化
		一个对象从无到有的过程 A a = new A() 1.JVM遇到new指令就会去堆内存分配一块内存空间,内存的大小在编译期间就可以确定 2.接着调用A的构造函数,这里构造的时候会沿着继承树逆流而上, ... 
- JVM之对象分配:栈上分配 & TLAB分配
		1. Java对象分配流程 2. 栈上分配 2.1 本质:Java虚拟机提供的一项优化技术 2.2 基本思想: 将线程私有的对象打散分配在栈上 2.3 优点: 2.3.1 可以在函数调用结束后自行销毁 ... 
- JVM(3)对象A和B循环引用,最后会不会不被GC回收?-------关于Java的GC机制
		①首先说一下,GC里边在JVM其中是使用的ROOT算法,ROOT算法,什么称作为ROOT呢,就是说类的静态成员,静态成员就是static修饰的那种,是"根"的一个,根还包含方法中的 ... 
- @JVM中对象的引用类型
		JVM中有四种引用类型:强引用.软引用.弱引用.虚引用 强引用(Stong Reference):是指在程序代码中普遍存在的,类似:Object obj = new Object()这类的引用,只 ... 
- JVM(二) 对象存活判断和垃圾回收算法
		对象的创建 概述 下面简要介绍创建对象的几个重要步骤 : 检查能否在常量池定位到一个类的符号引用,并检查这个符号代表的类是否已被加载,解析和初始化过.如果没有则执行类加载的操作.(即是说对象的引用放在 ... 
随机推荐
- vue 项目编译打包
			1. npm run build 2. npm install -g serve 3.serve dist 原文地址:https://www.cnblogs.com/jy13638593346/p/9 ... 
- Hibernate懒加载导致json数据对象传输异常的问题---(非常重要)
			1. 异常: [console_demo][WARN] [2016-12-15 19:49:35] org.springframework.web.servlet.mvc.support.Defaul ... 
- 强连通分量-----Kosaraju
			芝士: 有向图强连通分量在有向图G中,如果两个顶点vi,vj间(vi>vj)有一条从vi到vj的有向路径,同时还有一条从vj到vi的有向路径,则称两个顶点强连通(strongly connect ... 
- 数据采集之js埋点
			一.后台nginx环境搭建 web点数据采集后台配置nginx:https://blog.csdn.net/weixin_37490221/article/details/80894827 下载数据源 ... 
- HDU 1864 01背包、
			这题题意有点坑阿.感觉特别模糊. 我开始有一点没理解清楚.就是报销的话是整张整张支票报销的.也是我傻逼了 没一点常识 还有一点就是说单张支票总额不超过1000,每张支票中单类总额不超过600,我开始以 ... 
- Python--day47--mysql执行计划
			1,什么是mysql执行计划? 让mysql预估执行操作:在要执行的语句前面加explain,就不会真的执行sql语句,只是给出了要执行的数据的情况,如大约有多少条,查询类型. 
- [转]vue原理简介
			写vue也有一段时间了,对vue的底层原理虽然有一些了解,这里总结一下. vue.js中有两个核心功能:响应式数据绑定,组件系统.主流的mvc框架都实现了单向数据绑定,而双向绑定无非是在单向绑定基础上 ... 
- InetAddress与Socket
			InetAddress:构造方法私有,不能直接创建对象. InetAddress getByName(String host):在给定主机名的情况下确定主机的ip地址. InetAddress get ... 
- UVa 12325 - Zombie's Treasure Chest-[分类枚举]
			12325 Zombie’s Treasure Chest Some brave warriors come to a lost village. They are very lucky and fi ... 
- H3C VLSM
