new一个对象,java虚拟机做了什么?

这个问题一直困扰我很久,面试被问到好多次,但是都没有一个清晰的认识,然后最近在回头过来看下java基础回味下。

当刚写完一个java程序,main方法new一个对象,内存做了如下操作: 
一、初期: 
程序先进入编译时期,java编译器将程序代码编译成字节码信息;

二、中期—类加载和类连接

2.1类加载:首先通过类加载器将类class文件,加载到内存方法区,并创建java.lang.class类对象

2.2类连接: 
- 验证阶段:检验类的结构是否正确 
- 准备阶段:对类的变量进行分配内存,并默认初始化 
- 解析阶段:将二进制文件的符号引用(任何形式的字面值)解析为直接引用

三、后期(类和对象初始化) 
1. 如果new对象有引用变量指向它,栈内存存放引用变量指向null对象(未初始化,默认为null); 
2. new一个对象时,jvm会在堆内存中开辟一个空间存放该对象; 
3. 创建对象时,对象的成员(变量)先进行默认初始化;基本类型为基本类型默认值,引用类型为null,即引用变量的引用地址存放在栈(stack)内存中,对象的成员变量及值存放在堆内存中 
4. 对象成员初始化,对栈内存中的成员变量指定值; 
第一步显式初始化; 
第二步构造代码块初始化; 
5. 构造函数初始化,new是创建一个对象,使用构造函数进行初始化对象(默认有一个)。

注明:

在中期时,类加载指的是静态成员变量和静态代码块;
存在继承时: 
原则:先静后非,先父后子,先块后器 
执行顺序如下: 
第一步:父类静态成员变量(方法区) 
第二步:父类静态代码块(多个按照顺序执行) 
注意:根据静态代码块和变量位置顺序初始化变量 
第三步:子类静态成员变量(方法区) 
第四步:子类静态代码块 
第五步:父类成员变量和子类成员变量栈内存创建一片内存,指向值为null,先父类成员变量显式初始化(如果有的话) 
第六步:父类代码块(父类成员变量初始化) 
第七步:父类构造器 
第八步:子类成员变量显式初始化(如果有的话) 
第九步:子类代码块(子类成员变量初始化) 
第十步:子类构造器
例子分析:

class Base {
    private String name="base" ;
    public Base() {
        tellName();
        printName();
    }
    public void tellName() {
        System.out.println("Base tell name: " + name);
    }
    public void printName() {
        System.out.println("Base print name: " + name);
    }
}
public class Dervied extends Base {
    private String name = "dervied";
    public Dervied() {
        tellName();
        printName();
    }
    public void tellName() {
        System.out.println("Dervied tell name: " + name);
    }
    public void printName() {
        System.out.println("Dervied print name: " + name);
    }
    public static void main(String[] args){
        new Dervied();
    }
}

打印结果为:

Dervied tell name: null
Dervied print name:  null
Dervied tell name:  dervied
Dervied print name:  dervied

下来解释这程序过程:

声明父类成员变量name父=null,子类成员变量name=null;
显示初始化父类成员变量,name父=“base”;
执行父类构造器,执行tellName();方法,此处省略this关键字,实际是this.tellName(),this指当前对象Dervied子类,子类的name值还没有被初始化,所以默认为null,所以调用子类的tellName(),打印Dervied tell name: null,同理打印Dervied print name: null;
初始化子类成员变量name为dervied,所以打印 
Dervied tell name: dervied 
Dervied print name: dervied
这里单独分析类加载机制:APC

All 全盘负责:当一个类加载器加载某个类时,全盘负责将其类依赖的类一并加载;
Parent 父类委托:先父类加载器去试图加载该class,当父类加载器无法加载该class时,才从自己的类路径中加载该类;
Cache 缓存机制:缓存机制会将所有曾经类加载器加载过的类存入缓存中,当程序中需要某个类先去缓存中查找,如果查不到,则系统会读取该类的class文件继续缓存。这样算是为什么每次修改类后要重启JVM的原因
new一个对象给我们做了什么
964

new的过程 //创建对象用new关键字。那么这个new到底为我们做了什么呢? 有以下3步 // 1,在内存中开辟一块空间。 // 2, 在开辟的空中中创建对象。 // 3,调用对象...
--------------------- 
作者:你真的是一个很帅的程序媛 
来源:CSDN 
原文:https://blog.csdn.net/mrb1289798400/article/details/75637158 
版权声明:本文为博主原创文章,转载请附上博文链接!

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值