java对象创建(内存模型)过程详解

 2019-12-10 16:09  阅读(1954)
文章分类:Java Core

概述

java对象创建分为两个过程:声明对象引用和创建对象实体。类信息、对象引用、对象实体均在内存的不同区域。

内存结构

每一个java应用程序均会唯一的对应一个jvm实例,而这个jvm实例将会完成对象的内存分配、程序运行、垃圾回收等工作。JVM将其内存分为三个区域:方法区、栈区、堆区。

  • 方法区:是jvm在装载类文件时,用于存储类的所有描述信息的,这些信息主要包括,类的基本信息(访问修饰符、类名等)、字段信息(修饰符、类型、字段名)、方法信息(修饰符、返回值类型、方法名、参数列表类型、异常、方法体字节码等)、常量池、静态区、classloader以及class的引用
  • 栈区:存放局部变量,基本数据类型和对象引用类型
  • 堆区:用于存放new产生对象的实体,每一个对象实体均会有自己的内存地址,一旦这个内存地址不被任何栈区对象引用,就会成为垃圾,随时被gc回收

对象创建过程

package ccnu.allTest;

    public class TestObject {
        public static void main(String[] args) {
            YyPpLl ypl1 = new YyPpLl();
            YyPpLl ypl2 = new YyPpLl(48);
            System.out.println((ypl1.ii == ypl2.ii) + " "+ YyPpLl.ii);
            System.out.println(ypl1.str == ypl2.str);
        }

        static class YyPpLl {
            private String str = "ypl"; // 显示初始化字段
            private int i; // 未显示初始化字段
            private static int ii = 24; // 静态字段
            private static int iii;
            static { // 静态初始化块
                System.out.println("ii=" + ii + ", iii=" + iii);
            }
            { // 实例初始化块
    // iii = 100;
                System.out.println("str=" + str + ",i=" + i + ",ii=" + ii + ",iii=" + iii);
            }

            public YyPpLl(){
                ii = 72;
                System.out.println("non-arguments");
            }

            public YyPpLl(int i){
                this.i = i;
                System.out.println("two arguments");
            }

        }
    }

    /* ii=24, iii=0 str=ypl,i=0,ii=24,iii=0 non-arguments str=ypl,i=0,ii=72,iii=0 two arguments true 72 true */
  • 步骤:1、将JVM加载到内存
    2、jvm首先检查public类是否存在,存在就会将它加载到内存方法区中,否则抛出异常,结束进程
    3、对类中静态字段进行初始化(显示初始化就为指定的值,否则为默认值),接着执行静态代码块
    4、在栈中创建局部变量,堆中创建对象实体,为堆对象实体的成员变量(非静态)初始化,对于静态字段只需要从方法区的静态区中引用其值即可,执行构造代码块,接着执行构造函数(当然,调用顺序会一直上溯到Object类,每一个构造方法的第一行为super()语句),最后将对象实体堆地址给栈中引用变量

    要注意的是,实例字段包括自身定义的和从父类继承下来的(即使父类的实例字段被子类覆盖或者被private修饰,都照样为其分配内存)
    C++中的引用和JAVA的引用作对比,其实他们两个只是“名称”一样,本质并没什么关系,C++中的引用只是给现存变量起了一个别名(引用变量只是一个符号引用而已,编译器并不会给引用分配新的内存),而JAVA中的引用变量却是真真正正的变量,具有自己的内存空间,只是不同的引用变量可以“指向”同一个对象而已。因此,如果要拿C++和JAVA引用对象的方式相对比,C++中的指针倒和JAVA中的引用如出一辙,毕竟,JAVA中的引用其实就是对指针的封装

点赞(0)
版权归原创作者所有,任何形式转载请联系作者; Java 技术驿站 >> java对象创建(内存模型)过程详解

相关推荐