JVM
JVM:Java Virtual Machine,Java虚拟机,识别.class后缀文件,解析class的指令,调用操作系统函数完成操作。
JVM、JRE、JDK关系:JVM是运行核心,JRE提供基础类库,JDK(Java Development Kit) 让普通人也能做开发。
JVM内存结构
执行一个简单程序
public class Main{
public static void main(String[] args){
Student stu=new Student();
stu.copyWork();
stu.hashCode();
stu=null;
}
}
JVM内存结构:
- 堆(Heap) 最大内存共享区域
- 程序计数器(PC Register)
- 虚拟机栈(JVM Stacks)(线程)
- 本地方法栈(Native Method Stacks)
- 本地内存
- 元空间(metaspace)
- 直接内存(Direct memory)
执行引擎:
- Interpreter解释器
- JIT Compiler即时编译器
- GC垃圾回收
执行流程:
- 把Java源代码通过javac编译为Java字节码文件
- 通过java命令执行字节码,创建main主线程
- main主线程由虚拟机栈分配内存
- 发现Main类、Student类,触发类加载系统,把类的字节码加载到方法区。
- 发现 参数args 对象引用 都存放到main线程栈中
- 发现new Student() 创建对象存到堆中
- 执行方法 copyWork() hashCode() 都在栈中实现,一个方法一个栈帧
- 由程序计数器执行,记录当前线程执行第几行代码,保证下一次调度线程时能继续执行。
- 当stu=null时,没有其他地方调用后,当成是垃圾 进行GC垃圾回收
堆
最大内存共享区域,存储几乎所有的对象,GC操作对象也是堆。
- 普通对象
- JVM在堆上创建对象,其他地方使用它的引用。
- 把引用保存在虚拟机栈的局部变量表中。
- 基本数据类型
- 方法体内部声明的基本数据类型,直接在栈上分配。
- 其他区域声明,都在堆上分配。
栈
- 栈:基于线程的,与线程生命周期一样;
- 栈帧:栈中每一条数据 所有栈帧出栈后,线程结束。
- 局部变量表
- 操作数栈
- 动态连接
- 返回地址(returnAddress)
returnAddress就是指向特定指令内存地址的指针。
程序计数器
当前线程所执行字节码的行号指示器。存储的线程执行进度。
发生CPU时间片切换也能保持上一步操作继续执行。
元空间
存储:类的信息、常量池、方法数据、方法代码。
JVM内存溢出
程序计数器不会出现内存溢出情况。
-
内存溢出OutOfMemoryError情况:
- 堆内存耗尽:对象越来越多,一直在使用,不能被回收
- 方法区内存耗尽:加载的类越来越多,框架都需要运行期间动态生成新的类,一般看物理内存
- 虚拟机栈累积:每个线程最多1M内存,线程个数越来越多,长时间不销毁
-
出现Stack OverflowError区域
方法区、永久代、元空间关系
方法区:JVM规范中定义的一块内存区域,用来存储类元数据、方法字节码、即时编译器等信息
永久代:Hotspot虚拟机对JVM1.8之前的实现
元空间:Hotspot虚拟机对JVM1.8之后的实现,使用本地内存作为存储空间
metaSpace存储过程
- 堆中创建一个类加载器 Class loader Id1
- Student a=new Student(); Id1 会先加载Student类字节码,存储到元空间的方法区中,并在堆空间创建.Class对象,。
- a=new Student(); 在堆中创建Student的对象,创建实例a
- 当a和Student都不在被使用,GC开始运行。回收a,Student。
- 当类加载器也被回收后,元空间的数据才会清除。
JVM内存参数
- -Xmx10240m 内存可扩展最大值
- -Xms10240m 内存初始最小值
- -Xmn5120m 新生代最大内存
- -XX:SurivorRatio=3 eden区与from的占比3:1,还有一个to区与from相同
- -XX:NewRatio=2:1 老年代与新生代占比
- -XX:NewSize 新生代初始内存
- -XX:MaxNewSize 新生代内存可扩展最大值
- -XX:CompressedClassSpaceSize 类基本数据 默认1G
- -XX:MaxmetaspaceSize 元空间最大值
- -XX:ReservedCodeCacheSize 即时编译缓存机器码
- 小于240m 即时编译机器码的缓存都放在一起
- 大于240m 分为non-nmthodsJVM代码、profiled nmthods部分优化代码、non-profiled nmthods完整优化代码
- -Xss 线程栈 linux中最大内存1M