JVM如何加载.class文件
- JVM主要由Runtime Data Area,Class Loader,Execution Engine,Native Interface组成
- Class Loader: 依据特定格式,加载.class文件到内存
- Execution Engine: 对命令进行解析
- Native Interface: 融合不同开发语言的原生库为Java所用
- Runtime Data Area: JVM内存空间结构模型
什么是反射
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制
类从编译到执行的过程
- 编译器将Test.java源文件编译为Test.class字节码文件
- ClassLoader将字节码转换为JVM中的Class对象
- JVM利用Class对象实例化为Test对象
什么是ClassLoader
ClassLoader在Java中有着非常重要的作用,它主要工作在Class装载的加载阶段,其主要作用是从系统外部获得Class二进制数据流。它是Java的核心组件,所有的Class都是由ClassLoader进行加载的,ClassLoader负责通过将Class文件里的二进制数据流装载进系统,然后交给Java虚拟机进行连接,初始化等操作。
ClassLoader的种类
- BootStrapClassLoader: C++编写,加载核心库java.*
- ExtClassLoader: Java编写,加载扩展库javax.*
- AppClassLoader: Java编写,加载程序所在目录
- 自定义ClassLoader: Java编写,定制化加载
类的装载过程
- 加载: 通过ClassLoader加载class字节码文件,生成Class对象
- 链接:
- 校验: 检查加载的class的正确性和安全性
- 准备: 为类变量分配存储空间并设置类变量初始值
- 解析: JVM将常量池内的符号引用转换为直接引用
- 初始化: 执行类变量赋值和静态代码块
类的加载方式
- 隐式加载: new
- 显式加载: loadClass,forName等
loadClass和forName的区别
- Class.forName得到的class是已经初始化完成的
- ClassLoader.loaderClass得到的class是还没有链接的
JVM内存模型
- 线程私有: 程序计数器,虚拟机栈,本地方法栈
- 程序计数器:
- 当前线程所执行的字节码行号指示器(逻辑)
- 改变计数器的值来选取下一条需要执行的字节码指令
- 和线程是一对一的关系,即线程私有
- 对Java方法计数,如果是Native方法则计数器值为Undefined
- 不会发生内存泄漏
- Java虚拟机栈
- Java方法执行的内存模型
- 包含多个栈帧
- 局部变量表: 包含方法执行过程中的所有变量
- 操作数栈: 入栈,出栈,复制,交换,产生消费变量
- 本地方法栈: 与虚拟机栈相似,主要作用于标注了native的方法
- 程序计数器:
- 线程共享: MetaSpace,Java堆
- MetaSpace相比PermGen:
- 元空间使用本地内存,而永久代使用的是jvm的内存
- 字符串常量池存在永久代中,容易出现性能问题和内存溢出
- 类和方法的信息大小难以确定,给永久代的大小指定带来困难
- 永久代为GC带来不必要的复杂性
- 方便HotSpot与其他JVM如Jrockit的集成
- Java堆:
- 对象实例的分配区域
- GC管理的主要区域
- MetaSpace相比PermGen:
- 线程私有: 程序计数器,虚拟机栈,本地方法栈
JVM三大性能调优参数
- -Xms: 堆的初始值
- -Xmx: 堆能达到的最大值
- -Xss: 规定了每个线程虚拟机栈(堆栈)的大小
Java内存模型中堆和栈的区别
- 内存分配策略
- 静态存储: 编译时确定每个数据目标在运行时的存储空间需求
- 栈式存储: 数据区需求在编译时未知,运行时模块入口前确定
- 堆式存储: 编译时或运行时模块入口都无法确定,动态分配
- 联系:
- 引用对象,数组时,栈里定义变量保存堆中目标的首地址
- 区别:
- 管理方式: 栈自动释放,堆需要GC
- 空间大小: 栈比堆小
- 碎片相关: 栈产生的碎片远小于堆
- 分配方式: 栈支持静态和动态分配,而堆仅支持动态分配
- 效率: 栈的效率比堆高
- 内存分配策略
转载于:https://www.cnblogs.com/liuweiqc/p/11056059.html