4、Java 对象底层
来源:互联网 发布:网络监控显示不在线 编辑:程序博客网 时间:2024/06/15 08:23
Java对象创建
对象创建一共有四种方法(持续更新……)
使用New关键字创建对象
创建过程
从堆中划分内存的不同情况
内存分配完成后,虚拟机会将分配到的内存空间都初始化为0(不包括对象头),这保证了对象实例字段在Java代码中不初始化就可以直接使用。
接下来,执行< init>方法,使对象按照程序员的意愿进行初始化。
对象内存布局
在HotSpot虚拟机中,对象在内存中的存储的布局分为3块:对象头(Header)、实例数据(Instance Data)、对齐填充(Padding)
对象头
主要包括两部分信息
第一部分主要用于存储对象自身的运行时数据(如哈希码(HashCode)、GC分代年龄、锁状态标志、线程持有的锁、偏向线程ID、偏向时间戳等官方称这些数据为“Mark Word”)这些数据被设计固定的数据结构存储,它会根据对象状态复用自己存储空间。
以32位的HotSpot为例虚拟机对象头
对象头的另外一部分是指针类型,即对象指向它的类元数据的指针,虚拟机通过这个指针来确定该对象是哪个类的实例。并不是所有虚拟机实现都必须在对象数据上保留类型指针,即查找对象的元数据信息并不一定要经过对象本身,后续会讨论到(通过句柄访问对象时,句柄池内有对象类型数据指针)
实例数据
这部分的存储顺序会受到虚拟机分配策略参数(FieldsAllocationStyle)和字段在Java源码中定义顺序的影响。HotSpot虚拟机默认的分配策略为longs/doubles、ints、shorts/chars、bytes/booleans、oops(Ordinary Object Pointers),从分配策略中可以看出,相同宽度的字段总是被分配到一起。在满足这个前提条件的情况下,在父类中定义的变量会出现在子类之前。如果CompactFields参数值为true(默认为true),那子类之中较窄的变量也可能会插入到父类变量的空隙之中。
对齐填充
对齐填充并不是必然存在的,也没有特别的含义,它仅仅起着占位符的作用。由于HotSpot VM的自动内存管理系统要求对象起始地址必须是8字节的整数倍,换句话说就是对象的大小必须是8字节的整数倍。对象头部分正好似8字节的倍数(1倍或者2倍),因此当对象实例数据部分没有对齐的话,就需要通过对齐填充来补全。
对象的访问定位
建立对象是为了使用对象,我们的Java程序需要通过栈上的reference数据来操作堆上的具体对象。由于reference类型在Java虚拟机规范里面只规定了是一个指向对象的引用,并没有定义这个引用应该通过什么种方式去定位、访问到堆中的对象的具体位置,对象访问方式也是取决于虚拟机实现而定的。主流的访问方式有使用句柄和直接指针两种。
如果使用句柄访问的话,Java堆中将会划分出一块内存来作为句柄池,reference中存储的就是对象的句柄地址,而句柄中包含了对象实例数据与类型数据的具体各自的地址信息。如下图所示。
如果使用直接指针访问的话,Java堆对象的布局中就必须考虑如何放置访问类型数据的相关信息,reference中存储的直接就是对象地址,如下图所示。
这两种对象访问方式各有优势,使用句柄来访问的最大好处就是reference中存储的是稳定句柄地址,在对象被移动(垃圾收集时移动对象是非常普遍的行为)时只会改变句柄中的实例数据指针,而reference本身不需要被修改。
使用直接指针来访问最大的好处就是速度更快,它节省了一次指针定位的时间开销,由于对象访问的在Java中非常频繁,因此这类开销积小成多也是一项非常可观的执行成本。从上一部分讲解的对象内存布局可以看出,就虚拟机HotSpot而言,它是使用第二种方式进行对象访问,但在整个软件开发的范围来看,各种语言、框架中使用句柄来访问的情况也十分常见。
浅析String.intern()
String.intern( )在不同的JDK版本下可能会有不同运行方式(两者都会先到常量池中寻找,如果有均返回常量池中对象引用,下讨论常量池中无引用时)。
1、JDK1.6中运行时,intern方法会把首次遇到的字符串实例复制到永久代(代码区)去,返回的也是永久代中这个字符串实例的引用,而堆中创建对象地址必然不会等同于该引用地址
2、JDK1.7(及部分其他虚拟机,例如JRockit)的intern( )实现不会再复制实例,只是在常量池中记录首次出现实例的引用,因此intern返回的引用与堆中字符串实例是同一个,但不是首次出现的时候,会返回常量池中存在的那个引用。
- 4、Java 对象底层
- Java编程思想对象底层思想
- 复习创建java对象常见的一种的底层步骤
- Android Java对象和底层结构体转换
- Java底层
- java底层知识(4)--伪共享
- redis数据对象底层结构图
- 深入解析Java对象的hashCode和hashCode在HashMap的底层数据结构的应用
- 如何精确地测量java对象的大小-底层instrument API
- 深入解析Java对象的hashCode和hashCode在HashMap的底层数据结构的应用
- 深入解析Java对象的hashCode和hashCode在HashMap的底层数据结构的应用
- Java语言中Object对象的hashCode()取值的底层算法是怎样实现的?
- 深入解析Java对象的hashCode和hashCode在HashMap的底层数据结构的应用
- 深入解析Java对象的hashCode和hashCode在HashMap的底层数据结构的应用
- Java面向对象-枚举的定义和特点以及底层分析
- Java语言中Object对象的hashCode()取值的底层算法是怎样实现的?
- 深入解析Java对象的hashCode和hashCode在HashMap的底层数据结构的应用
- java语言中Object对象的hashCode()取值的底层算法是怎样实现的
- 三种最常见最短路算法 及其 应用范围
- 深度学习汇报系列:(三、四)概率与优化
- ubuntu正确的密码一直卡在登录界面
- luaError json解析错误1
- [lesson4]用USB连接console
- 4、Java 对象底层
- Win32API学习笔记第五章(一)
- windons实现Yang Liu的Topical Word Embeddings
- 关于swap的两种实现的说明
- JVM中类的卸载机制
- 七、Wampserver3.0.6自定义虚拟目录、多站点配置及端口号的更改
- [Effective Java Second Edition]创建实例的5种方式
- spring boot默认配置文件application.properties的属性读取
- jquery中attr和prop的区别