JVM加载对象时内存加载顺序

简介: 在开发中,有时会遇到这样的情况:我明明给一个变量赋值了,为什么在使用该变量时却是没有值的,这个和JVM的内存加载顺序有关,当你使用该变量时,这个变量还没初始化完成。 首先我们来看一段代码:public class ObjectLoadMemoryTest extend...

在开发中,有时会遇到这样的情况:我明明给一个变量赋值了,为什么在使用该变量时却是没有值的,这个和JVM的内存加载顺序有关,当你使用该变量时,这个变量还没初始化完成。
首先我们来看一段代码:

public class ObjectLoadMemoryTest extends FuTest{

    private int INT =100;
    private final int FINAL_INT =100;
    private final Integer FINAL_INTEGER = 100;
    private static Integer STATIC_INTEGER = 100;
    private String STR1 = "abc";
    private final String FINAL_STR1="abc";
    private final String FINAL_STR2 = new String("abc");
    private final List<String> FINAL_LIST = new ArrayList<String>();

    public ObjectLoadMemoryTest() {
        System.out.println("ObjectLoadMemoryTest开始执行构造。。。。。。");
        doDisplay();
    }

    @Override
    public void doDisplay() {
        System.out.println(INT);
        System.out.println(FINAL_INT);
        System.out.println(FINAL_INTEGER);
        System.out.println(STATIC_INTEGER);
        System.out.println(STR1);
        System.out.println(FINAL_STR1);
        System.out.println(FINAL_STR2);
        System.out.println(FINAL_LIST);
    }

    public static void main(String[] args) {
        new ObjectLoadMemoryTest();
    }


}

abstract class FuTest{

    public FuTest(){
        System.out.println("FuTest构造开始执行。。。。。");
        doDisplay();
    }

    public abstract void doDisplay();
}

这段代码的逻辑很简单,就是在初始化子类对象的时候,调用这个类中的方法doDisplay,这个方法会打印该类中的所有的属性,我们可以通过观察打印结果来分析一下jvm在创建对象的时候,内存是如何加载的。
运行结果如下:

FuTest构造开始执行。。。。。
0
100
null
100
null
abc
null
null
ObjectLoadMemoryTest开始执行构造。。。。。。
100
100
100
100
abc
abc
abc
[]

我们发现在调用子类的构造函数的时候,会先调用父类的构造,在父类中我们同样会打印所有的属性,发现和子类中打印的结果是不一样的。
通过打印结果,我们可以分析到以下几点:

  • 基本数据类型的默认初始化是在构造函数之前,但是其显示初始化却是在调用父类构造函数之后执行的
  • 使用final修饰的基本数据类型及String类型,在调用父类构造函数之前就已经显示初始化完成了
  • 即使使用了final修饰,属性如果是一个对象,那么它也会在调用父类构造函数之后执行
  • 使用static修饰的属性,都是在调用父类构造之前就显示初始化了

由此,我们可以推断出如下结果:
类的加载过程:
1、启动JVM,加载程序中需要使用的class文件。
2、在加载class文件的时候,所有的静态内容(静态成员变量,静态成员函数,静态代码块)都要加载到方法区的静态区中。
3、当类中的所有静态加载完成之后,开始给类中的所有静态成员变量默认初始化。
4、类中的所有静态成员变量默认初始化完成之后,开始给这些静态成员变量显示赋值。
5、所有静态成员变量显示赋值结束之后,开始运行类中的静态代码块。
6、当所有的静态代码块执行完成,代表当前这个class文件才彻底被加载结束。

对象的创建过程:
1、使用new关键字创建对象,在堆给对象分配内存空间。
2、给对象所属类中的所有非静态成员变量分配空间并进行默认的初始化。
3、执行和new对象时传递参数一致的构造函数。
4、执行构造函数的的过程中有隐式的三步:
4.1、执行super() 语句,找父类的空参数构造函数
4.2、给非静态成员变量进行显示赋值。
4.3、运行构造代码块
4.4、构造函数中的自己写的代码执行。
5、构造函数执行完成,对象创建结束。

目录
相关文章
|
17天前
|
缓存 算法 Java
JVM知识体系学习六:JVM垃圾是什么、GC常用垃圾清除算法、堆内存逻辑分区、栈上分配、对象何时进入老年代、有关老年代新生代的两个问题、常见的垃圾回收器、CMS
这篇文章详细介绍了Java虚拟机(JVM)中的垃圾回收机制,包括垃圾的定义、垃圾回收算法、堆内存的逻辑分区、对象的内存分配和回收过程,以及不同垃圾回收器的工作原理和参数设置。
39 4
JVM知识体系学习六:JVM垃圾是什么、GC常用垃圾清除算法、堆内存逻辑分区、栈上分配、对象何时进入老年代、有关老年代新生代的两个问题、常见的垃圾回收器、CMS
|
7天前
|
存储 算法 Java
聊聊jvm的内存结构, 以及各种结构的作用
【10月更文挑战第27天】JVM(Java虚拟机)的内存结构主要包括程序计数器、Java虚拟机栈、本地方法栈、Java堆、方法区和运行时常量池。各部分协同工作,为Java程序提供高效稳定的内存管理和运行环境,确保程序的正常执行、数据存储和资源利用。
28 10
|
5天前
|
缓存 监控 Java
在使用 Glide 加载 Gif 动画时避免内存泄漏的方法
【10月更文挑战第20天】在使用 Glide 加载 Gif 动画时,避免内存泄漏是非常重要的。通过及时取消加载请求、正确处理生命周期、使用弱引用、清理缓存和避免重复加载等方法,可以有效地避免内存泄漏问题。同时,定期进行监控和检测,确保应用的性能和稳定性。需要在实际开发中不断积累经验,根据具体情况灵活运用这些方法,以保障应用的良好运行。
|
6天前
|
存储 算法 Java
Java虚拟机(JVM)的内存管理与性能优化
本文深入探讨了Java虚拟机(JVM)的内存管理机制,包括堆、栈、方法区等关键区域的功能与作用。通过分析垃圾回收算法和调优策略,旨在帮助开发者理解如何有效提升Java应用的性能。文章采用通俗易懂的语言,结合具体实例,使读者能够轻松掌握复杂的内存管理概念,并应用于实际开发中。
|
16天前
|
存储 监控 算法
JVM调优深度剖析:内存模型、垃圾收集、工具与实战
【10月更文挑战第9天】在Java开发领域,Java虚拟机(JVM)的性能调优是构建高性能、高并发系统不可或缺的一部分。作为一名资深架构师,深入理解JVM的内存模型、垃圾收集机制、调优工具及其实现原理,对于提升系统的整体性能和稳定性至关重要。本文将深入探讨这些内容,并提供针对单机几十万并发系统的JVM调优策略和Java代码示例。
42 2
|
17天前
|
Java 测试技术 Android开发
让星星⭐月亮告诉你,强软弱虚引用类型对象在内存足够和内存不足的情况下,面对System.gc()时,被回收情况如何?
本文介绍了Java中四种引用类型(强引用、软引用、弱引用、虚引用)的特点及行为,并通过示例代码展示了在内存充足和不足情况下这些引用类型的不同表现。文中提供了详细的测试方法和步骤,帮助理解不同引用类型在垃圾回收机制中的作用。测试环境为Eclipse + JDK1.8,需配置JVM运行参数以限制内存使用。
26 2
|
15天前
|
存储 Kubernetes 架构师
阿里面试:JVM 锁内存 是怎么变化的? JVM 锁的膨胀过程 ?
尼恩,一位经验丰富的40岁老架构师,通过其读者交流群分享了一系列关于JVM锁的深度解析,包括偏向锁、轻量级锁、自旋锁和重量级锁的概念、内存结构变化及锁膨胀流程。这些内容不仅帮助群内的小伙伴们顺利通过了多家一线互联网企业的面试,还整理成了《尼恩Java面试宝典》等技术资料,助力更多开发者提升技术水平,实现职业逆袭。尼恩强调,掌握这些核心知识点不仅能提高面试成功率,还能在实际工作中更好地应对高并发场景下的性能优化问题。
|
3月前
|
存储 编译器 C语言
【C语言篇】数据在内存中的存储(超详细)
浮点数就采⽤下⾯的规则表⽰,即指数E的真实值加上127(或1023),再将有效数字M去掉整数部分的1。
298 0
|
5天前
|
存储 C语言
数据在内存中的存储方式
本文介绍了计算机中整数和浮点数的存储方式,包括整数的原码、反码、补码,以及浮点数的IEEE754标准存储格式。同时,探讨了大小端字节序的概念及其判断方法,通过实例代码展示了这些概念的实际应用。
13 1
|
10天前
|
存储
共用体在内存中如何存储数据
共用体(Union)在内存中为所有成员分配同一段内存空间,大小等于最大成员所需的空间。这意味着所有成员共享同一块内存,但同一时间只能存储其中一个成员的数据,无法同时保存多个成员的值。