美文网首页Java 技术
Java 类的加载过程对象的创建过程

Java 类的加载过程对象的创建过程

作者: 撑起头顶的天 | 来源:发表于2018-01-31 10:46 被阅读9次

    1.类加载过程及对象创建过程

    1.1 类加载过程:

    1, JVM会先去方法区中找有没有相应类的.class存在。如果有,就直接使用;如果没有,则把相关类的.class加载到方法区
    2, 在.class加载到方法区时,会分为两部分加载:先加载非静态内容,再加载静态内容
    3, 加载非静态内容:把.class中的所有非静态内容加载到方法区下的非静态区域内
    4, 加载静态内容:
    4.1、把.class中的所有静态内容加载到方法区下的静态区域内
    4.2、静态内容加载完成之后,对所有的静态变量进行默认初始化
    4.3、所有的静态变量默认初始化完成之后,再进行显式初始化
    4.4、当静态区域下的所有静态变量显式初始化完后,执行静态代码块
    5,当静态区域下的静态代码块,执行完之后,整个类的加载就完成了。

    1.2 对象创建过程:

    1, 在堆内存中开辟一块空间

    2, 给开辟空间分配一个地址

    3, 把对象的所有非静态成员加载到所开辟的空间下

    4, 所有的非静态成员加载完成之后,对所有非静态成员变量进行默认初始化

    5, 所有非静态成员变量默认初始化完成之后,调用构造函数

    6, 在构造函数入栈执行时,分为两部分:先执行构造函数中的隐式三步,再执行构造函数中书写的代码

    6.1、隐式三步:
        1,执行super语句
        2,对开辟空间下的所有非静态成员变量进行显式初始化
        3,执行构造代码块
    6.2、在隐式三步执行完之后,执行构造函数中书写的代码
    

    7,在整个构造函数执行完并弹栈后,把空间分配的地址赋值给一个引用对象

    总结类中能书写的成员

    栈: 用来运行函数。可以存储局部信息

    特点:先进后出

    堆:用来存储实体(被new创建出来的)。

    特点:

    1,  每一个实体所开辟的空间都有一个地址
    
    2,  每一个实体中存储的数据都有一个默认初始值
    

    方法区:

    存放class和static。 方法区其实是由N多个小的区域构成。有存放非静态内容的非静态区域,还有存放静态内容的静态区域,还有存放常量的常量池等

    图解创建过程

    对象创建过程

    代码注释创建过程

    class Person {  
        int age;  
      
        Person(int age) {  
            this.age = age;  
        }  
    }  
      
    class Student extends Person {
        // 1, 非静态成员加载完成之后,对所有非静态成员变量进行默认初始化
        // String school = null;    
        // 3,对开辟空间下的所有非静态成员变量进行显式初始化  
        String school = "abc";  
      
        Student(String school, int age) {  
            // 2,执行super语句  
            super(age);  
            // 5、在隐式三步执行完之后,执行构造函数中书写的代码  
            this.school = school;  
        }  
      
        {  
            // 4,执行构造代码块  
            System.out.println("Student code block");  
        }  
    }  
    

    类的组成

    class  ABC
    {
             非静态成员变量
             静态成员变量
     
            非静态成员函数
            静态成员函数
     
    构造函数:ABC(...){...}
     
    静态代码块: static {...}
    构造代码块 :  {...}
    }
    

    2.栈堆内存

    栈:

    保存局部变量的值,包括:1.用来保存基本数据类型的值;2.保存类的实例,即堆区对象的引用(指针)。也可以用来保存加载方法时的帧。

    堆:

    用来存放动态产生的数据,比如new出来的对象。注意创建出来的对象只包含属于各自的成员变量,并不包括成员方法。因为同一个类的对象拥有各自的成员变量,存储在各自的堆中,但是他们共享该类的方法,并不是每创建一个对象就把成员方法复制一次。

    无非就是两种类型的变量:基本类型和引用类型。二者作为局部变量,都放在栈中,基本类型直接在栈中保存值,引用类型只保存一个指向堆区的指针,真正的对象在堆里。作为参数时基本类型就直接传值,引用类型传指针。

    小结

    1.分清什么是实例什么是对象。Class a= new Class();此时a叫实例,而不能说a是对象。实例在栈中,对象在堆中,操作实例实际上是通过实例的指针间接操作对象。多个实例可以指向同一个对象。

    2.栈中的数据和堆中的数据销毁并不是同步的。方法一旦结束,栈中的局部变量立即销毁,但是堆中对象不一定销毁。因为可能有其他变量也指向了这个对象,直到栈中没有变量指向堆中的对象时,它才销毁,而且还不是马上销毁,要等垃圾回收扫描时才可以被销毁。

    3.以上的栈、堆、代码段、数据段等等都是相对于应用程序而言的。每一个应用程序都对应唯一的一个JVM实例,每一个JVM实例都有自己的内存区域,互不影响。并且这些内存区域是所有线程共享的。这里提到的栈和堆都是整体上的概念,这些堆栈还可以细分。

    4.类的成员变量在不同对象中各不相同,都有自己的存储空间(成员变量在堆中的对象中)。而类的方法却是该类的所有对象共享的,只有一套,对象使用方法的时候方法才被压入栈,方法不使用则不占用内存。

    Java堆内存(heap memory)的十个要点

    1. Java堆内存是操作系统分配给JVM的内存的一部分。

    2. 当我们创建对象时,它们存储在Java堆内存中。

    3. 为了便于垃圾回收,Java堆空间分成三个区域,分别叫作New Generation, Old Generation或叫作Tenured Generation,还有Perm Space。

    4. 你可以通过用JVM的命令行选项 -Xms, -Xmx, -Xmn来调整Java堆空间的大小。不要忘了在大小后面加上”M”或者”G”来表示单位。举个例子,你可以用 -Xmx256m来设置堆内存最大的大小为256MB。(Xms表示起始的堆内存大小,Xmx表示最大的堆内存的大小。另外有一个参数 -Xmn,它表示new generation的大小)

    5. 你可以用JConsole或者 Runtime.maxMemory(), Runtime.totalMemory(), Runtime.freeMemory()来查看Java中堆内存的大小。

    6. 你可以使用命令“jmap”来获得heap dump,用“jhat”来分析heap dump。

    7. Java堆空间不同于栈空间,栈空间是用来储存调用栈和局部变量的。

    8. Java垃圾回收器是用来将死掉的对象(不再使用的对象)所占用的内存回收回来,再释放到Java堆空间中。

    9. 当你遇到java.lang.outOfMemoryError时,不要紧张,有时候仅仅增加堆空间就可以了,但如果经常出现的话,就要看看Java程序中是不是存在内存泄露了。

    10. 请使用Profiler和Heap dump分析工具来查看Java堆空间,可以查看给每个对象分配了多少内存。

    http://www.jianshu.com/p/251b1bf72cd8

    赞赏

    微信
           支付宝

    相关文章

      网友评论

        本文标题:Java 类的加载过程对象的创建过程

        本文链接:https://www.haomeiwen.com/subject/vbrkzxtx.html