Java 类的加载过程对象的创建过程
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)的十个要点
-
Java堆内存是操作系统分配给JVM的内存的一部分。
-
当我们创建对象时,它们存储在Java堆内存中。
-
为了便于垃圾回收,Java堆空间分成三个区域,分别叫作New Generation, Old Generation或叫作Tenured Generation,还有Perm Space。
-
你可以通过用JVM的命令行选项 -Xms, -Xmx, -Xmn来调整Java堆空间的大小。不要忘了在大小后面加上”M”或者”G”来表示单位。举个例子,你可以用 -Xmx256m来设置堆内存最大的大小为256MB。(Xms表示起始的堆内存大小,Xmx表示最大的堆内存的大小。另外有一个参数 -Xmn,它表示new generation的大小)
-
你可以用JConsole或者 Runtime.maxMemory(), Runtime.totalMemory(), Runtime.freeMemory()来查看Java中堆内存的大小。
-
你可以使用命令“jmap”来获得heap dump,用“jhat”来分析heap dump。
-
Java堆空间不同于栈空间,栈空间是用来储存调用栈和局部变量的。
-
Java垃圾回收器是用来将死掉的对象(不再使用的对象)所占用的内存回收回来,再释放到Java堆空间中。
-
当你遇到java.lang.outOfMemoryError时,不要紧张,有时候仅仅增加堆空间就可以了,但如果经常出现的话,就要看看Java程序中是不是存在内存泄露了。
-
请使用Profiler和Heap dump分析工具来查看Java堆空间,可以查看给每个对象分配了多少内存。
http://www.jianshu.com/p/251b1bf72cd8
赞赏
微信支付宝