当前位置:首页 > 科技  > 软件

深入理解Java虚拟机:对象实例化及直接内存详解

来源: 责编: 时间:2024-04-10 08:37:47 128观看
导读前言在Java世界中,万物皆对象。当我们谈论一个对象时,其实质是指代一段具有特定属性和行为的内存区域。在JVM的视角下,对象的存储并非简单的字节序列堆积,而是遵循着严谨的结构设计与管理规则。从创建到消亡,一个Java对象

前言

在Java世界中,万物皆对象。当我们谈论一个对象时,其实质是指代一段具有特定属性和行为的内存区域。在JVM的视角下,对象的存储并非简单的字节序列堆积,而是遵循着严谨的结构设计与管理规则。从创建到消亡,一个Java对象在JVM中的生命历程主要围绕堆内存展开,而堆正是JVM内存模型中用于存储对象实例的主要区域。V4V28资讯网——每日最新资讯28at.com

本文将围绕对象的实例化、对象内存布局、对象的访问定位和直接内存展开介绍说明。V4V28资讯网——每日最新资讯28at.com

对象实例化

图片图片V4V28资讯网——每日最新资讯28at.com

创建对象的方式

最常见的方式new、Xxx的静态方法,XxxBuilder/XxxFactory的静态方法:V4V28资讯网——每日最新资讯28at.com

Student student = new Student();

Class的newInstance方法:反射的方式,只能调用空参的构造器,权限必须是public:V4V28资讯网——每日最新资讯28at.com

Class clazz = Class.forName("org.yian.Student");Student student = (Student) clazz.newInstance();

Constructor的newInstance(XXX):反射的方式,可以调用空参、带参的构造器,权限没有要求:V4V28资讯网——每日最新资讯28at.com

Student.class.getConstructor().newInstance();

使用clone():不调用任何的构造器,要求当前的类需要实现Cloneable接口,实现clone():V4V28资讯网——每日最新资讯28at.com

Student clone = student.clone();

使用序列化:从文件中、从网络中获取一个对象的二进制流:V4V28资讯网——每日最新资讯28at.com

public class Student implements Serializable {    private String name;    private Integer age;     public String getName() {        return name;    }     public void setName(String name) {        this.name = name;    }     public Integer getAge() {        return age;    }     public void setAge(Integer age) {        this.age = age;    }     public void say() {        System.out.println("hello i'm yian!"+this.age);    }      public static void main(String[] args) throws Exception {         Student student = new Student();        student.setAge(10);        String filePath = "com";        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(filePath));        oos.writeObject(student);        oos.close();        System.out.println("序列化完成!");         ObjectInputStream ois = new ObjectInputStream(new FileInputStream(filePath));        Student student1 = (Student) ois.readObject();        ois.close();        student1.say();        System.out.println("反序列化完成!");     }}

第三方库 Objenesis:V4V28资讯网——每日最新资讯28at.com

Objenesis objenesis = new ObjenesisStd();ObjectInstantiator<Student> instantiator = objenesis.getInstantiatorOf(Student.class);Student st = instantiator.newInstance();

创建对象的步骤

字节码分析对象创建

javap -v -p Student.class:V4V28资讯网——每日最新资讯28at.com

图片图片V4V28资讯网——每日最新资讯28at.com

  • new:会首先检查这个Class有没有加载,即加载、链接、初始化?并按照编译中的大小信息分配空间,进行创建对象 ,并对其临时初始化
  • dup:第一句new会在操作数栈中生成一个指向该对象的引用,dup指令会将这个引用再复制一遍,放到操作数栈的栈顶,上面那个引用是作为一个句柄指向方法区的对应方法。
  • invokespecial :进行真实初始化,为其赋实际的初始值【即调用构造器方法<init>】

注意:V4V28资讯网——每日最新资讯28at.com

<init>与<clinit>的区别:前者是一个类的构造器在字节码中对应的方法,后者习惯被称为类构造器方法,他会在类加载的初始化阶段对类的静态部分进行初始化【如静态代码块,静态成员变量等】V4V28资讯网——每日最新资讯28at.com

JVM创建对象的步骤

1.判断对象对应的类是否加载、链接、初始化V4V28资讯网——每日最新资讯28at.com

虚拟机遇到一条new指令,首先去检查这个指令的参数能否在Metaspace的常量池中定位到一个类的符号引用,并且检查这个符号引用代表的类是否已经被加载,解析和初始化(即判断类元信息是否存在)V4V28资讯网——每日最新资讯28at.com

如果没有,那么在双亲委派模式下,使用当前类加载器以ClassLoader + 包名 + 类名为key进行查找对应的.class文件;V4V28资讯网——每日最新资讯28at.com

  • 如果没有找到文件,则抛出ClassNotFoundException异常
  • 如果找到,则进行类加载,并生成对应的Class对象

2.为对象分配内存V4V28资讯网——每日最新资讯28at.com

首先计算对象占用空间的大小,接着在堆中划分一块内存给新对象。如果实例成员变量是引用变量,仅分配引用变量空间即可,即4个字节大小V4V28资讯网——每日最新资讯28at.com

如果内存规整:虚拟机将采用的是指针碰撞法(Bump The Point)来为对象分配内存。V4V28资讯网——每日最新资讯28at.com

  • 所有用过的内存在一边,空闲的内存放另外一边,中间放着一个指针作为分界点的指示器,分配内存就仅仅是把指针指向空闲那边挪动一段与对象大小相等的距离罢了。如果垃圾收集器选择的是Serial、ParNew这种基于压缩算法的,虚拟机采用这种分配方式。一般使用带Compact(整理)过程的收集器时,使用指针碰撞

如果内存不规整:虚拟机需要维护一个空闲列表(Free List)来为对象分配内存V4V28资讯网——每日最新资讯28at.com

  • 已使用的内存和未使用的内存相互交错,那么虚拟机将采用的是空闲列表来为对象分配内存。意思是虚拟机维护了一个列表,记录上那些内存块是可用的,再分配的时候从列表中找到一块足够大的空间划分给对象实例,并更新列表上的内容

选择哪种分配方式由Java堆是否规整所决定,而Java堆是否规整又由所采用的垃圾收集器是否带有压缩整理功能决定。V4V28资讯网——每日最新资讯28at.com

3.处理并发问题V4V28资讯网——每日最新资讯28at.com

  • 采用CAS失败重试、区域加锁保证更新的原子性
  • 每个线程预先分配一块TLAB:通过设置-XX:+UseTLAB参数来设定

4.初始化分配到的内存V4V28资讯网——每日最新资讯28at.com

所有属性设置默认值,保证对象实例字段在不赋值时可以直接使用V4V28资讯网——每日最新资讯28at.com

5.设置对象的对象头V4V28资讯网——每日最新资讯28at.com

  • Mark Word:存储对象自身的运行时元数据,如哈希码(HashCode)、GC分代年龄、锁状态标志、偏向线程ID等。这些信息直接影响对象的内存管理、线程同步以及方法调用等操作
  • 类型指针:指向方法区中的类型信息,如类的元数据、方法表、常量池等。通过类型指针,JVM能够快速定位到对象所属类的详细定义,实现方法调度、字段访问等操作

6.执行init方法进行初始化V4V28资讯网——每日最新资讯28at.com

在Java程序的视角看来,初始化才正式开始。初始化成员变量,执行实例化代码块,调用类的构造方法,并把堆内对象的首地址赋值给引用变量V4V28资讯网——每日最新资讯28at.com

对象初始化初始化顺序为:默认 -> 显式或静态代码块 -> 构造方法 -> setterV4V28资讯网——每日最新资讯28at.com

对象内存布局

图片图片V4V28资讯网——每日最新资讯28at.com

对象头

对象头包含了两部分,分别是运行时元数据和类型指针。如果是数组,还需要记录数组的长度。V4V28资讯网——每日最新资讯28at.com

运行时元数据:V4V28资讯网——每日最新资讯28at.com

  • 哈希值(HashCode)
  • GC分代年龄
  • 锁状态标志
  • 线程持有的锁
  • 偏向线程ID
  • 偏向时间戳

类型指针:V4V28资讯网——每日最新资讯28at.com

  • 指向类元数据InstanceKlass,确定该对象所属的类型

实例数据

它是对象真正存储的有效信息,包括程序代码中定义的各种类型的字段(包括从父类继承下来的和本身拥有的字段)V4V28资讯网——每日最新资讯28at.com

  • 相同宽度的字段总是被分配在一起
  • 父类中定义的变量会出现在子类之前
  • 如果CompactFields参数为true(默认为true):子类的窄变量可能插入到父类变量的空隙

对齐填充

不是必须的,也没有特别的含义,仅仅起到占位符的作用V4V28资讯网——每日最新资讯28at.com

小结:

public class Customer{    int id = 1001;    String name;    Account acct;    {        name = "匿名客户";    }    public Customer() {        acct = new Account();    }}public class CustomerTest{    public static void main(string[] args){        Customer cust = new Customer();    }}

图片图片V4V28资讯网——每日最新资讯28at.com

对象的访问定位

图片图片V4V28资讯网——每日最新资讯28at.com

JVM是如何通过栈帧中的对象引用访问到其内部的对象实例?V4V28资讯网——每日最新资讯28at.com

句柄访问

图片图片V4V28资讯网——每日最新资讯28at.com

reference中存储稳定句柄地址,对象被移动(垃圾收集时移动对象很普遍)时只会改变句柄中实例数据指针即可,reference本身不需要被修改V4V28资讯网——每日最新资讯28at.com

直接指针(HotSpot采用)

图片图片V4V28资讯网——每日最新资讯28at.com

直接指针是局部变量表中的引用,直接指向堆中的实例,在对象实例中有类型指针,指向的是方法区中的对象类型数据V4V28资讯网——每日最新资讯28at.com

直接内存

不是虚拟机运行时数据区的一部分,也不是《Java虚拟机规范》中定义的内存区域。直接内存是在Java堆外的、直接向系统申请的内存区间。来源于NIO,通过存在堆中的DirectByteBuffer操作Native内存。通常,访问直接内存的速度会优于Java堆,即读写性能高V4V28资讯网——每日最新资讯28at.com

非直接缓存区

图片图片V4V28资讯网——每日最新资讯28at.com

使用IO读写文件,需要与磁盘交互,需要由用户态切换到内核态。在内核态时,需要两份内存存储重复数据,效率低。V4V28资讯网——每日最新资讯28at.com

直接缓存区

图片图片V4V28资讯网——每日最新资讯28at.com

使用NIO时,操作系统划出的直接缓存区可以被java代码直接访问,只有一份。NIO适合对大文件的读写操作。V4V28资讯网——每日最新资讯28at.com

本文链接:http://www.28at.com/showinfo-26-82512-0.html深入理解Java虚拟机:对象实例化及直接内存详解

声明:本网页内容旨在传播知识,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。邮件:2376512515@qq.com

上一篇: 让我们从零开始详解 Elasticsearch

下一篇: 2024 抖音欢笑中国年之编辑器技巧与实践

标签:
  • 热门焦点
  • Redmi Pad评测:红米充满野心的一次尝试

    Redmi Pad评测:红米充满野心的一次尝试

    从Note系列到K系列,从蓝牙耳机到笔记本电脑,红米不知不觉之间也已经形成了自己颇有竞争力的产品体系,在中端和次旗舰市场上甚至要比小米新机的表现来得更好,正所谓“大丈夫生居
  • 6月iOS设备性能榜:M2稳居榜首 A系列只能等一手3nm来救

    6月iOS设备性能榜:M2稳居榜首 A系列只能等一手3nm来救

    没有新品发布,自然iOS设备性能榜的上榜设备就没有什么更替,仅仅只有跑分变化而产生的排名变动,毕竟苹果新品的发布节奏就是这样的,一年下来也就几个移动端新品,不会像安卓厂商,一
  • Raft算法:保障分布式系统共识的稳健之道

    Raft算法:保障分布式系统共识的稳健之道

    1. 什么是Raft算法?Raft 是英文”Reliable、Replicated、Redundant、And Fault-Tolerant”(“可靠、可复制、可冗余、可容错”)的首字母缩写。Raft算法是一种用于在分布式系统
  • 之家push系统迭代之路

    之家push系统迭代之路

    前言在这个信息爆炸的互联网时代,能够及时准确获取信息是当今社会要解决的关键问题之一。随着之家用户体量和内容规模的不断增大,传统的靠"主动拉"获取信息的方式已不能满足用
  • JVM优化:实战OutOfMemoryError异常

    JVM优化:实战OutOfMemoryError异常

    一、Java堆溢出堆内存中主要存放对象、数组等,只要不断地创建这些对象,并且保证 GC Roots 到对象之间有可达路径来避免垃 圾收集回收机制清除这些对象,当这些对象所占空间超过
  • 雅柏威士忌多款单品价格大跌,泥煤顶流也不香了?

    雅柏威士忌多款单品价格大跌,泥煤顶流也不香了?

    来源 | 烈酒商业观察编 | 肖海林今年以来,威士忌市场开始出现了降温迹象,越来越多不断暴涨的网红威士忌也开始悄然回归市场理性。近日,LVMH集团旗下苏格兰威士忌品牌雅柏(Ardbeg
  • 大厂卷向扁平化

    大厂卷向扁平化

    来源:新熵作者丨南枝 编辑丨月见大厂职级不香了。俗话说,兵无常势,水无常形,互联网企业调整职级体系并不稀奇。7月13日,淘宝天猫集团启动了近年来最大的人力制度改革,目前已形成一
  • 三星折叠屏手机去年销售近1000万台 今年目标定为1500万

    三星折叠屏手机去年销售近1000万台 今年目标定为1500万

    7月29日消息,三星率先发力可折叠手机市场,在全球市场已经取得了非常亮眼的成绩,接下来会进一步巩固和扩大这一优势。三星在推出Galaxy Z Flip5和Galax
  • 2022爆款:ROG魔霸6 冰川散热系统持续护航

    2022爆款:ROG魔霸6 冰川散热系统持续护航

    喜逢开学季,各大商家开始推出自己的新产品,进行打折促销活动。对于忠实的端游爱好者来说,能够拥有一款梦寐以求的笔记本电脑是一件十分开心的事。但是现在的
Top