jvm体系结构用一张图来表示就是:
JVM的内部体系结构分为三部分
类装载器(ClassLoader)子系统
作用: 用来装载.class文件,
分类
java自带加载器:根、扩展、系统类加载器
根类记载器:使用c++编写,程序员无法在java代码中获得该类
扩展加载器:使用java代码实现
系统加载器(应用加载器):使用java代码实现
用户自定义加载器:java.lang.classloader的子类
类的加载、连接与初始化
1、加载:查找并加载类的二进制数据,类的加载的最终产品是位于堆区中的Class对象,class对象封装了类在方法区中的数据结构,并且向java程序员提供访问方法区内的数据结构的接口
2、连接:类被加载后就进入链接阶段,该阶段将已经读入到内存的类的二进制数据合并到虚拟机的运行时环境中。
验证:确保class文件符合字节码要求
准备:将类的class文件从硬盘上加载到内存里,静态变量属于类
Private static int a=3;
准备阶段a的初始值为**0**
解析:
3、初始化:为类的静态变量赋予正确的初始值
初始化时将a的值变成3,初始化时仍没有对象生成
Private static int a;
Static {
a=3;
}
Static{
a=4;
}
这个例子更加清晰,从上到下顺序执行a-》0-》3-》4;
执行引擎
作用:执行字节码,或者执行本地方法
运行时数据区
方法区,堆,java栈,PC寄存器,本地方法栈
方法区:用于存储类结构信息,如常量池、域、方法数据、方法体、构造函数,包括类中的专用方法,实例初始化,接口初始化都存储在这个区域,是堆中的永久带
运行时常量池:编译期的数字常量、方法或者域的引用
本地方法栈:运行Native方法准备的空间
类加载器的父类委托机制
在此委托机制中,除了java虚拟机自带的根类加载器以外,其余的类加载器都有且只有一个父类加载器,当java程序请求加载器loaer1加载sample类时,loader1首先委托自己的父加载器在加载sample类,若父加载器能加载,则由父加载器加载,否则由加载器loader1本身加载samlpe类。
如图所示:
从上图可知,类加载器的加载顺序是由下向上依次请求,如果子类加载器无该对象,则由它的上一层继续加载,以此类推。
优点:
父类委托机制能够提高系统安全性,举个例子java.lang.Object类总是由根类加载器加载,其他任何用户自定义的类加载器都不可能加载含有恶意代码的java.lang.Object类
内存分配策略
静态内存分配
程序编译时已经确定每个数据在运行时的存储空间需求,不允许有可变数据结构和嵌套或递归结构
栈内存分配
又动态,程序对数据区的需求在编译期时完全未知,只有在运行时才能知道。
堆内存分配
只有在真正运行到某行代码时才能确定要分配的内存大小。优势:动态分配内存大小
栈和线程绑定,开启一个线程时就创建了一个栈
堆主要用来存储对象,栈主要用来执行程序
所有被根对象引用的对象为活动对象,不能被回收,而其他相互引用的对象将被回收,因为没有被根对象引用