• 浅析对象的创建过程


    个人博客

    http://www.milovetingting.cn

    浅析对象的创建过程

    前言

    我们平时在创建对象时,可能都会这样创建:

    Object object = new Object();
    

    看起来很简单的一个过程,那么这个new操作的背后,有哪些相关的知识点,是需要我们掌握的,本文针对这些来展开介绍。

    对象的创建过程.png

    对象的创建过程

    类都是由JVM加载到内存中的,类加载采用双亲委派机制,双亲委派机制具体信息,这里不作展开。类加载包含以下几个过程:

    加载

    加载Class信息到内存中,可以从Class文件读取,也可以从Zip包读取,或者在运行时通过动态代理读取。

    连接

    验证

    验证Class文件的字节流中包含的信息是否符合虚拟机要求。

    准备

    为类对象的成员变量分配内存并设置类的成员变量的初始值

    解析

    虚拟机将常量池中的符号引用替换为直接引用

    初始化

    执行类构造器的init方法。

    使用

    对象的使用过程。

    卸载

    当类的所有对象都释放后执行卸载。

    创建方式

    对象的创建方式可以直接通过new的方式来创建,但一般为便于实现对象全局唯一,都会通过单例为实现。

    单例的实现简单来分,有以下几种:

    • 饿汉式

    • 懒汉式

    • 静态内部类

    • 枚举

    饿汉式

    private static Singleton instance = new Singleton();
    
        private Singleton() {
    
        }
    
        public Singleton getInstance() {
            return instance;
        }
    

    饿汉式存在的问题是不能按需加载。

    懒汉式

    线程不安全

    private static Singleton instance;
    
        private Singleton() {
    
        }
    
        public Singleton getInstance() {
            if (instance == null) {
                instance = new Singleton();
            }
            return instance;
        }
    

    存在的问题:多线程的情况下,线程不安全。

    线程安全

    方法加锁
    private static Singleton instance;
    
        private Singleton() {
    
        }
    
        public synchronized Singleton getInstance() {
            if (instance == null) {
                instance = new Singleton();
            }
            return instance;
        }
    

    通过方法加锁,线程安全的问题是解决了,但是每次获取实例都会加锁,增加了开销。

    代码加锁
    直接加载
    private static Singleton instance;
    
        private Singleton() {
    
        }
    
        public Singleton getInstance() {
            if (instance == null) {
                synchronized (Singleton.class) {
                    instance = new Singleton();
                }
            }
            return instance;
        }
    

    锁不加在方法上,而是加在具体的代码块上。这种方式会存在创建两个对象的情况。

    双重检查锁
    • 双重检查锁-不加Volatile
    private static Singleton instance;
    
        private Singleton() {
    
        }
    
        public Singleton getInstance() {
            if (instance == null) {
                synchronized (Singleton.class) {
                    if (instance == null) {
                        instance = new Singleton();
                    }
                }
            }
            return instance;
        }
    

    这种方式不会存在创建两个对象的情况。但会存在指令重排的问题。

    • 双重检查锁-加Volatile

    private static volatile Singleton instance;

    private Singleton() {
    
    }
    
    public Singleton getInstance() {
        if (instance == null) {
            synchronized (Singleton.class) {
                if (instance == null) {
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
    

    静态内部类

    private Singleton() {
    
        }
    
        public Singleton getInstance() {
            return SingletonHolder.INSTANCE;
        }
    
        static class SingletonHolder {
            private static Singleton INSTANCE = new Singleton();
        }
    

    静态内部类的方式可以实现按需加载。

    枚举

    public enum Singleton {
    
        INSTANCE;
    
        public void doSomething() {
            
        }
    }
    

    对象的内存结构

    具体的可以参考上一篇文章。

    对象头

    Mark Word

    包含HashCode,锁标识,对象年龄等信息。

    Klass Pointer

    对象的Class的内存地址

    Length

    这个只在数组类型的对象中存在,用来存放数组长度。

    实例数据

    存放对象的非静态成员变量信息。

    对齐填充

    JVM要求8字节对齐

    对象分配

    从GC的角度,可以将Java的堆分为新生代老年代。新生代和老年代的大小比为:1:2。

    新生代

    用来存放新产生的对象。新生代又分为Eden、SurvivorFrom、SurvivorTo三个区域,比例为:8:1:1。新生代使用的GC算法是复制算法。

    Eden区

    新对象产生后保存的地方。如果是较大的对象,则直接进入老年代。

    SurvivorFrom区

    GC后保留下来的对象会保存在这个区域。

    SurvivorTo区

    SurvivorFrom在GC后保留下来的对象会进入这个区域。

    老年代

    新生代中的对象每经过一次GC后,对应的年龄就会+1,如果对象的年龄达到老年代的标准(默认15次),则会进入老年代。老年代使用的GC算法是标记清除算法。

  • 相关阅读:
    选择
    随便写了一个CodeToDbTable可生成(含备注)sql脚本(基于hibernate实体)
    分享一个k8s的mysql-router配置
    因为一个外接国外项目要求英文,故用python简单写的中文页面文件转英文
    thinkpad e450 win7黑苹果macos 10.10.5(网/显/声卡驱动)安装成功
    爆栈之前端工程化技术小结(备案)
    使用Pytorch实现简单的人脸二分类器
    链表的反转
    合唱队
    字节跳动——机器人跳跃问题
  • 原文地址:https://www.cnblogs.com/milovetingting/p/12931494.html
Copyright © 2020-2023  润新知