前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Java 对象深入探究

Java 对象深入探究

作者头像
付威
发布2021-03-11 11:12:43
2820
发布2021-03-11 11:12:43
举报

这篇博客是为了深入探究 Java 中对象的知识。

对象的创建

首先我们先看下一个简单创建对象的代码,看一个对象到底是如何在内存中创建的。

public static void main(String[] args) {
        Person obj = new Person();
    }


public class Person {
    private int age=8;
    private String name="fu";

}

对应的 JVM 指令:

0 new #2 <learnJava/AQS/Person>
3 dup
4 invokespecial #3 <learnJava/AQS/Person.<init>>
7 astore_1
8 return

对应指令含义:

new: 创建一个实例对象。

dup: 复制栈顶数值并将复制值压入栈顶

invokespecial:调用超类构建方法, 实例初始化方法, 私有方法

astore_1:将栈顶引用类型数值存入指定本地变量

具体的初始化过程如下:

image-20210307232154928
image-20210307232154928

DCL 和 volatitle 的问题

在常用的单例模式中,有一个 double check 模式 ,具体代码如下:

private volatile static Singleton05 singleton05;
	//double check 性能最好
	public static Singleton05 getInstance() {
		if (singleton05 == null) {
			synchronized (Singleton05.class) {
				if (singleton05 == null) {
					singleton05 = new Singleton05();
				}
			}
		}
		return singleton05;
	}

在诸多的单例模式中, double check lock 是性能和简单的方式之一,在上面对象的定义中,使用了 volatitle 的关键字描述,如果此时我们没有使用 volatitlte 关键字会怎样?

image-20210308231542469
image-20210308231542469

因为在初始化的时候,存在一个半初始化的状态,其实是已经创建的对象,但是对象中的字段为 0,此时 DCL 检查不为空的时候,则满足了条件,即会直接返回,导致意想不到的结果。

Volatitle 关键字有两个作用

  1. 对象的内存区域加一个内存屏障,防止指令重排序。
  2. 锁定 CPU 和内存空间总线,让每一个线程的数据保持最新。

对象在内存中的存储布局

Java 对象一般分为 3 块空间:对象头实例数据对齐空间。在数组对象中又单独增加的数据长度的空间,具体几个对象布局如下:

image-20210309223629055
image-20210309223629055

问题: 一个 Object 占用几个字节?

答案:16 字节,算法分为两种:

  1. 不开启指针压缩: 8+8+0+0 = 16
  2. 开启类指针压缩: 8+4+0+4 = 16

如果是 Object obj=new Object(); 则 obj 占用了 4 个字节,所以一共占用了 20 字节。

压缩对类指针和 压缩对象指针

在对象中一般会保留类的引用,称为类指针(Class Pointer)。同样,指向实例也会有一个指针,称为对象指针(OOP)。这个指针一般是 8 个字节,压缩后变成 4 个字节。

image-20210309230720613
image-20210309230720613

为什么要存在指针压缩呢?目的肯定是为了节省内存,为什么压缩指针能行的通呢?我个人觉得有两个原因:

对象都是 8 字节对齐的,所以指针后都是相对的 “整数“(能整除 8)

例如: (不是 JVM 的指针压缩,只是表达指针压缩的含义)
16  00000000 00001000
32  00000000 00010000
64  00000000 00100000 
可以转为:
  //舍弃 3 个 0 
16  00000000 00001 000
32  00000000 00010 000
64  00000000 00100 000
  1. 类指针和对象指针的寻址范围一般不会超过 4 字节,2^32 =4G(一旦超过这个值,则压缩失效)

在 JVM 中有两个参数来控制指针

UseCompressClassPointers : 类指针压缩

UseCompressOop : 对象指针压缩

对象的分配规则

  • 允许在栈上直接分配开关打开,优先在栈上分配,对象如果想在栈上分配需要有两个条件:
  1. 标量替换:用成员变量代替对象。
  2. 不产生逃逸:不会被其他方法引用
  • 在栈上分配空间效率比较高,直接 pop ,没有 GC 的过程。
  • 如果栈空间不够用了,如果对象过大,直接进入老年区。
  • 如果不大,会进入 edian 区,符合线程 ==本地分配== (进入线程独有的 buffer TLAB,不存在锁竞争,效率比较高),进入线程本地分配,不满足进入 edian 区。
image-20210309230952555
image-20210309230952555
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2021-03-072,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 对象的创建
  • DCL 和 volatitle 的问题
  • 对象在内存中的存储布局
  • 压缩对类指针和 压缩对象指针
  • 对象的分配规则
相关产品与服务
文件存储
文件存储(Cloud File Storage,CFS)为您提供安全可靠、可扩展的共享文件存储服务。文件存储可与腾讯云服务器、容器服务、批量计算等服务搭配使用,为多个计算节点提供容量和性能可弹性扩展的高性能共享存储。腾讯云文件存储的管理界面简单、易使用,可实现对现有应用的无缝集成;按实际用量付费,为您节约成本,简化 IT 运维工作。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档