Java内存区域:
1:程序计数器:java虚拟机是通过多线程轮流切换并分配处理器执行时间方式来实现的,在任何一个确定的时间内,一个处理器都只会执行一条线程上的指令,因此,为了使线程切换后能恢复到一个正确的执行位置,每条线程都会有一个独立的程序计数器,各条线程之间互相不影响,独立存储这类内存区域就是线程所独有的内存
2:java虚拟机栈:方法执行的时候所建立的一个栈,存储了局部变量以及操作数,动态链接,
3:java堆:大多数应用,java堆可以是连续的也可以是不连续的,保存了对象地址。
4:方法区:和堆一样,也是各个线程所共享,用来存储已经被虚拟机加载的类信息,常量,静态变量等等。(Non-Heap)。
类加载:
1:类加载的场景
a:当遇到new关键字的时候,如果类没有初始化,就会触发其初始化
b:当使用java反射包对类进行反射调用的时候,
c:当初始化一个类的时候,如果发现他的父类没有初始化,那么就会触发其父类的初始化
d:当虚拟机启动的过程中,需要指定一个程序的入口,也就是main函数的时候,虚拟机就会先初始化这个类。
类的加载过程:
1:加载 2:验证 准备,解析 3:初始化 4:使用5:卸载
1:通过一个类的全名来获取这个类的二进制字节流
2:将这个类所代表的静态存储结构转换为方法区的运行时数据结构
3:在内存中生成这个类的Class对象。作为方法区的这个类的各种数据入口
2:验证
验证阶段,就是判断字节流是否符合Class文件的规范,同时还根据静态代码的执行顺序,赋初始值
3:初始化
再次根据程序启动来赋值
对象的加载过程:
JVM遇到new关键字,会自动去堆内存中开辟存储空间,根据类的表述,会对非静态成员变量分配下变量空间,同时还会对非静态成员设置默认值,然后会调用构造函数进栈。执行构造函数之前,会先去看看是否有父类,执行下Super。然后会去执行构造代码块{ }。接着给对象中的函数赋显示值。然后执行构造函数,最后才是出栈。
双亲委派模型:如果一个类加载器收到了类加载的请求,它首先不会自己去尝试加载这个类,而是把这个请求委派给父类加载器去完成,每一个层次的加载器都是如此,因此所有的加载请求最终都会传送到顶层的启动类加载器中,只有当父加载器反馈自己无法完成这个请求时,子加载器才会去进行自己尝试加载。简洁点就是:越是基础的类,就会被越上级的加载器所进行加载。
好处是:java类随着它的类加载器一起具备了一种层级关系,例如Object类,无论那一个类加载这个类,最终都是委托给处于模型最顶端的类来加载,因此Object类在所有的类加载器都是同一个类。
如果不是这样,那么可以自己建立一个Object类,然后自己去加载,这样java类体系就会出现混乱。