2.JVM虚拟机-对象的创建过程

JVM虚拟机-对象的创建过程

目录

1.创建对象的方式

2.new对象的创建过程

2.1对象创建检查:

2.2虚拟机为对象分配内存

2.2.1.内存分配方式1-指针碰撞:

2.2.2.内存分配方式2-空闲列表:

2.2.3.为对象分配内存时的线程安全问题:

2.3 对象初始化


本文是针对学习《深入理解java虚拟机》2.3章,对象创建部分的学习笔记

1.创建对象的方式

package com.zhe.yang.java.jvm.createObject;

import java.io.*;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

public class Demo implements Cloneable, Serializable {

    private int id;

    /*get  set 方法省略*/

    public Demo() {
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }

    @Override
    public String toString() {
        return "Demo{" +
                "id=" + id +
                '}';
    }

    public static void main(String[] args) throws IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException, CloneNotSupportedException, IOException {
        /*使用new 关键字创建对象*/
        Demo demo = new Demo(123);
        //System.out.println("使用反射通过无参构造函数创建对象:"+demo.toString());

        /*使用反射通过无参构造函数创建对象*/
        Demo demo1 = Demo.class.newInstance();
        //System.out.println("使用反射通过无参构造函数创建对象:"+demo1.toString());

        /*使用反射通过有参构造函数创建对象*/
        Constructor<Demo> constructor = Demo.class.getConstructor(int.class);
        Demo demo2 = constructor.newInstance(234);
        //System.out.println("使用反射通过有参构造函数创建对象:"+demo2.toString());

        /*通过克隆对象*/
        Demo clone = (Demo)demo1.clone();
        //System.out.println("通过克隆对象:"+clone.toString());

        /*通过序列化与反序列化创建对象*/
        ObjectOutputStream outputStream=new ObjectOutputStream(new FileOutputStream("demo_serializable"));
        outputStream.writeObject(demo);
        outputStream.close();

        ObjectInputStream objectInputStream=new ObjectInputStream(new FileInputStream("demo_serializable"));
        try {
            Demo demo_serializable = (Demo)objectInputStream.readObject();
            //System.out.println("通过序列化与反序列化创建对象:"+demo_serializable.toString());
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}

 

2.new对象的创建过程

 

2.1对象创建检查:

虚拟机在执行new指令时,首先检查这个指令参数能否在常量池中确定到一个类的符号引用,并且检查这个符号引用的类是否被加载解析和初始化过。如果没有,必须先执行相应的类加载过程。

 

2.2虚拟机为对象分配内存

在类加载检查通过后,虚拟机将为新生对象分配内存。对象所需内存的大小在类加载完成后就可以完全确定,为对象分配内存的任务等同于把一块确定大小的内存从堆中划分出来。

内存分配引出的问题:内存分配方式与线程安全问题。

堆内存是否规整由所采用的垃圾收集器是否带有压缩整理决定

2.2.1.内存分配方式1-指针碰撞:

假设堆中内存是绝对规整,已用过的内存放在一边,空闲的内存放在一边,中间放着一个指针作为分界点的指示器,那所分配内存就是将指针向空闲内存空间挪动一段与对象大小相等的距离,这种方式为“指针碰撞”。

在使用Serial,ParNew等带有Compact过程的收集器时,采用此重方式。

 

2.2.2.内存分配方式2-空闲列表:

如果堆中内存不是规整的,已使用的内存和空闲内存相互交错,虚拟机必须维护一个列表,记录哪些内存块可用,在分配时从列表中找到足够大的空间划分给对象实例,并更新列表上的记录,这种方式为“空闲列表

在使用CMS这种基于mark-sweep算法收集器时,采用空闲列表。

 

2.2.3.为对象分配内存时的线程安全问题:

现象:正在给对象A分配内存,指针还没来得及修改,对象B又同时使用原来的指针分配内存的情况

解决方法1:对分配内存空间的动作进行同步处理-实际上虚拟机采用CAS配上失败重试的方式保证更新操作的原子性

解决方法2:把内存分配的动作按照线程划分在不同的空间中进行,即每个线程在堆中预先分配一小块内存,称为“本地线程分配缓冲”(TLAB)。哪个线程要分配内存,就在哪个线程的TLAB上分配,只有TLAB用完并分配新的TLAB时,才需要同步锁定。虚拟机是否使用TLAB,可通过-XX:+/-UseTLAB参数来设定。TLAB是在堆上分配给线程的私有内存

 

2.3 对象初始化

a. 内存分配后,虚拟机需要将分配的内存空间都初始化为零值(不包括对象头),如果使用TLAB,这一过程提前到TLAB分配时进行。此操作保证对象的实例字段在java代码中可以不赋初始值就可直接使用

b. 设置对象头的相关信息,对象头中包含类实例,元数据信息,hash,GC分代年龄等,以及锁信息等。

c. 上面步骤执行后虚拟机层面的创建对象完成,从java程序的视角看,对象创建才刚开始<init>方法还没执行,所有字段都为0.执行new指令后接着执行<init>方法,按照代码进行初始化。

d.初始化完成后,对象创建完毕。

说明:在对象创建时,new关键字使用<init>方法,接<invokespecial>完成,而其他方式创建对象,使用<invokevirtual>方式创建。具体解释说明,以及对象的初始化,类加载等会在以后进行学习讲解。

附对象创建方式的main方法的字节码,用于观察创建命令:

public static void main(java.lang.String[]) throws java.lang.IllegalAccessException, java.lang.InstantiationException, java.lang.NoSuchMethodException, java.lang.reflect.InvocationTargetException, java.lang.CloneNotSupportedException, java.io.IOException;
    descriptor: ([Ljava/lang/String;)V
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=5, locals=9, args_size=1
         0: new           #11                 // class com/zhe/yang/java/jvm/createObject/Demo
         3: dup
         4: bipush        123
         6: invokespecial #12                 // Method "<init>":(I)V
         9: astore_1
        10: ldc           #11                 // class com/zhe/yang/java/jvm/createObject/Demo
        12: invokevirtual #13                 // Method java/lang/Class.newInstance:()Ljava/lang/Object;
        15: checkcast     #11                 // class com/zhe/yang/java/jvm/createObject/Demo
        18: astore_2
        19: ldc           #11                 // class com/zhe/yang/java/jvm/createObject/Demo
        21: iconst_1
        22: anewarray     #14                 // class java/lang/Class
        25: dup
        26: iconst_0
        27: getstatic     #15                 // Field java/lang/Integer.TYPE:Ljava/lang/Class;
        30: aastore
        31: invokevirtual #16                 // Method java/lang/Class.getConstructor:([Ljava/lang/Class;)Ljava/lang/reflect/Constructor;
        34: astore_3
        35: aload_3
        36: iconst_1
        37: anewarray     #17                 // class java/lang/Object
        40: dup
        41: iconst_0
        42: sipush        234
        45: invokestatic  #18                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
        48: aastore
        49: invokevirtual #19                 // Method java/lang/reflect/Constructor.newInstance:([Ljava/lang/Object;)Ljava/lang/Object;
        52: checkcast     #11                 // class com/zhe/yang/java/jvm/createObject/Demo
        55: astore        4
        57: aload_2
        58: invokevirtual #20                 // Method clone:()Ljava/lang/Object;
        61: checkcast     #11                 // class com/zhe/yang/java/jvm/createObject/Demo
        64: astore        5
        66: new           #21                 // class java/io/ObjectOutputStream
        69: dup
        70: new           #22                 // class java/io/FileOutputStream
        73: dup
        74: ldc           #23                 // String demo_serializable
        76: invokespecial #24                 // Method java/io/FileOutputStream."<init>":(Ljava/lang/String;)V
        79: invokespecial #25                 // Method java/io/ObjectOutputStream."<init>":(Ljava/io/OutputStream;)V
        82: astore        6
        84: aload         6
        86: aload_1
        87: invokevirtual #26                 // Method java/io/ObjectOutputStream.writeObject:(Ljava/lang/Object;)V
        90: aload         6
        92: invokevirtual #27                 // Method java/io/ObjectOutputStream.close:()V
        95: new           #28                 // class java/io/ObjectInputStream
        98: dup
        99: new           #29                 // class java/io/FileInputStream
       102: dup
       103: ldc           #23                 // String demo_serializable
       105: invokespecial #30                 // Method java/io/FileInputStream."<init>":(Ljava/lang/String;)V
       108: invokespecial #31                 // Method java/io/ObjectInputStream."<init>":(Ljava/io/InputStream;)V
       111: astore        7
       113: aload         7
       115: invokevirtual #32                 // Method java/io/ObjectInputStream.readObject:()Ljava/lang/Object;
       118: checkcast     #11                 // class com/zhe/yang/java/jvm/createObject/Demo
       121: astore        8
       123: goto          133
       126: astore        8
       128: aload         8
       130: invokevirtual #34                 // Method java/lang/ClassNotFoundException.printStackTrace:()V
       133: return

 

参考资料:

1.《深入理解java虚拟机》2.3章节

2. 参考博客《https://blog.csdn.net/justloveyou_/article/details/72466416

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
ava实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),可运行高分资源 Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现
C语言是一种广泛使用的编程语言,它具有高效、灵活、可移植性强等特点,被广泛应用于操作系统、嵌入式系统、数据库、编译器等领域的开发。C语言的基本语法包括变量、数据类型、运算符、控制结构(如if语句、循环语句等)、函数、指针等。下面详细介绍C语言的基本概念和语法。 1. 变量和数据类型 在C语言中,变量用于存储数据,数据类型用于定义变量的类型和范围。C语言支持多种数据类型,包括基本数据类型(如int、float、char等)和复合数据类型(如结构体、联合等)。 2. 运算符 C语言中常用的运算符包括算术运算符(如+、、、/等)、关系运算符(如==、!=、、=、<、<=等)、逻辑运算符(如&&、||、!等)。此外,还有位运算符(如&、|、^等)和指针运算符(如、等)。 3. 控制结构 C语言中常用的控制结构包括if语句、循环语句(如for、while等)和switch语句。通过这些控制结构,可以实现程序的分支、循环和多路选择等功能。 4. 函数 函数是C语言中用于封装代码的单元,可以实现代码的复用和模块化。C语言中定义函数使用关键字“void”或返回值类型(如int、float等),并通过“{”和“}”括起来的代码块来实现函数的功能。 5. 指针 指针是C语言中用于存储变量地址的变量。通过指针,可以实现对内存的间接访问和修改。C语言中定义指针使用星号()符号,指向数组、字符串和结构体等数据结构时,还需要注意数组名和字符串常量的特殊性质。 6. 数组和字符串 数组是C语言中用于存储同类型数据的结构,可以通过索引访问和修改数组中的元素。字符串是C语言中用于存储文本数据的特殊类型,通常以字符串常量的形式出现,用双引号("...")括起来,末尾自动添加'\0'字符。 7. 结构体和联合 结构体和联合是C语言中用于存储不同类型数据的复合数据类型。结构体由多个成员组成,每个成员可以是不同的数据类型;联合由多个变量组成,它们共用同一块内存空间。通过结构体和联合,可以实现数据的封装和抽象。 8. 文件操作 C语言中通过文件操作函数(如fopen、fclose、fread、fwrite等)实现对文件的读写操作。文件操作函数通常返回文件指针,用于表示打开的文件。通过文件指针,可以进行文件的定位、读写等操作。 总之,C语言是一种功能强大、灵活高效的编程语言,广泛应用于各种领域。掌握C语言的基本语法和数据结构,可以为编程学习和实践打下坚实的基础。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值