Java代码是如何执行的
java文件
javac命令编译
class文件,存放字节码,class文件也是二进制文件
介于源代码和机器码之间的中间表示
类的生命周期
类从被加载到虚拟机内存中开始,直到卸载出内存为止,它的整个生命周期包括了:加载、验证、准备、解析、初始化、使用和卸载这7个阶段。其中,验证、准备和解析这三个部分统称为连接(linking)。
加载 - 加载字节流加载为内存的类对象
验证 - 校验字节流格式、类中使用的关键字校验
准备 - 分配内存并赋默认值
解析 - 符号引用变直接引用
初始化 - 执行类构造器方法,为常量值的字段赋值
使用、 卸载
类加载器
jvm如何管理内存
内存分配+内存回收
jvm内存模型
模型结构和组成部分
堆 - 线程共享
对象年龄分代
新生代,占1/3
Eden
新对象首先分配到Eden,连续内存,指针碰撞分配,非常快
Survivor1/2 两个区
满了触发MinorGc,可达性分析,存活者先到s1,年龄+1,记录对象头中
老年代,占2/3
年龄达到15,移动至老年代
优化参数
有大量持续存活的大对象时可以适度提升老年代比例
栈 - 线程私有 - 生命周期与线程相同(随线程而生,随线程而灭)。
本地方法栈 - 线程私有
是指C/C++写的代码,会使用native关键字修饰,一般是jdk中偏底层和操作系统直接交互的代码。
方法区 - 线程共享
存储已被虚拟机加载的类元信息、方法元信息、静态变量、常量池,其中引用类型变量实际存储在堆区,方法区存储的是引用地址。方法区无法满足内存分配需求时,抛出OutOfMemoryError。JVM规范并没对这个区域实现垃圾收集,因为这个区域回收主要针对的是类信息、方法信息、常量池的信息回收,回收结果往往难以令人满意。
【jdk1.7-】 永久代(PermSpace) - 实际上是从堆中划分的内存,使用的是虚拟机内存
永久代的缺点:
【jdk1.8+】 元空间(Metaspace) - 使用操作系统直接管理的内存
调优案例
程序计数器
程序计数器能保留当前线程执行的方法,如果方法不是native方法,计数器会保存正在执行的字节码指令地址。如果是native方法,则保存的是undefined。
线程私有。为了线程切换后能恢复到正确的执行位置,每条线程都需要一个独立的程序计数器。
程序计数器是唯一一个在Java虚拟机规范中没有规定OOM(OutOfMemoryError)情况的区域。
jvm内存调优
调优的重点主要集中在堆内存,其次是方法区,而虚拟机栈和本地方法栈通常只在特定问题下调整。
类的加载
类加载器
分类
启动类加载器(BootStrap ClassLoader, 又称根加载器)
每次执行 java 命令时都会使用该加载器为虚拟机加载核心类。 该加载器是由 native code 实现,而不是 Java 代码,加载类的路径为 <JAVA_HOME>/jre/lib。重点包含rt.jar、jce.jar、resource.jar
扩展类加载器(Extension ClassLoader)
应用程序类加载器(System ClassLoader)
自定义类加载器(Custom ClassLoader)、
双亲委派模型
加载流程
对象回收
垃圾回收算法
数据库执行
数据库优化
索引