一、定义二、JVM内存结构
1. 程序计数器2. 虚拟机栈
定义栈内存溢出线程运行诊断 3. 本地方法栈 Native Method Stacks4. 堆
堆内存溢出 5. 方法区
一、定义Java Virtual Machine --java的运行环境(java二进制字节码的运行环境)
JVM提供的功能:
一次编写,到处运行自动内存管理,垃圾回收功能数组下标越界检查多态
比较(包含关系)
JVM
JRE:JVM+基础类库 Java RuntimeEnvironment
JDK:JVM+基础类库+编译工具
开发JavaSE: JDK+IDE
开发JavaEE:JDK+应用服务器+IDE
jvm是一套规范eg :HotSpot,Oracle JDK
二、JVM内存结构java源代码-> 二进制字节码(jvm指令)->解释器->解释为机器码->CPU
1. 程序计数器作用:记住下一条jvm指令的执行地址
特点:
是线程私有的(每个线程有自己的程序计数器)不会存在内存溢出 2. 虚拟机栈 定义
栈-线程运行需要的内存空间
栈帧组成
一个栈帧对应一次方法的调用 每个方法运行时需要的内存
包含的信息有:参数,局部变量,返回地址等
当方法执行完,就把这个栈帧弹出
总结
每个线程运行时需要的内存,称为虚拟机栈每个栈由多个栈帧组成,对应着每次方法调用时所占用的内存每个线程只能有一个活动栈帧,对应着当前正在执行的那个方法
问题
- 垃圾回收是否涉及栈内存? no 不需要垃圾回收。GC回收堆内存中的对象划分更多栈内存? 不会提升效率方法内的局部变量是否线程安全? (线程中变量有无共享?)
每个线程各有一个栈,线程中的每个方法各有一个栈帧,调用时放到该线程的栈里。 共享的变量才要考虑线程安全问题
递归没有合理的结束条件(栈帧过多导致栈溢出)栈帧过大导致栈溢出 线程运行诊断
- CPU占用过多死锁
不是java代码编写的接口。其他语言的本地方法接口需要使用本地方法栈
native
作用:给本地方法的运行提供内存空间
4. 堆通过new关键字,创建对象都会使用堆内存
特点:
它是有线程共享的,堆中对象都需要考虑线程安全的问题有垃圾回收机制 堆内存溢出
OutOfMemoryError: Java heap space
堆内存诊断:
- jps工具 查看进程 jpsjmap 查看堆内存占用情况 jmap -heap 进程idjconsole 图形界面 jdk自带
案例:垃圾回收后,内存占用仍然很高
jvisualvm
点击[堆dump] 可以截取快照
线程内共享的区域,存与类相关的信息
方法区在虚拟机启动时被创建,逻辑上是堆的组成部分方法区也会导致内存溢出。
1.8以前导致永久代内存溢出
1.8以后会导致元空间内存溢出
元空间内存溢出
场景: Spring MyBatis
运行时常量池
二进制字节码组成:类基本信息,常量池,类方法定义-包含了虚拟机指令
.class javap -v Helloworld.class
常量池就是一张表,虚拟机指令根据这张常量表找到要执行的类名、方法名、参数类型、字面量等信息
运行时常量池,常量池是*.class文件中的,当该类被加载,它的常量池信息就会放入运行时常量池,并把里面的符号地址变为真实地址(内存中的地址)。



