JVM位置/体系结构
- 栈:
- 内容:8大基本数据类型、局部变量、引用变量,基本方法;
- 栈内存特点,数据一执行完毕,变量会立即释放,节约内存空间,不存在回收;
- 栈内存中的数据,没有默认初始化值,需要手动设置
- 生命周期与线程同步
- 堆:
- 线程共享;
- 堆内存用来存放new创建的对象和数组。
- 堆内存中所有的实体都有内存地址值。
- 堆内存中的实体是用来封装数据的,这些数据都有默认初始化值。
- 堆内存中的实体不再被指向时,JVM启动垃圾回收机制,自动清除,这也是JAVA优于C++的表现之一(C++中需要程序员手动清除)
- 堆分区
- 新生区: 类在此诞生、成长,死亡
- 伊甸园区:所有类在此被new出来
- 幸存区from/幸存区to. : 谁空谁是to,位置不断交换
- 老年区: 默认超过15次gc清理不掉的,参数可以设置
- 永久区(元空间):用来存放JDK自身的运行环境或类信息,不存在垃圾回收;关闭虚拟机就会释放内存;有常量池、方法区
- 新生区: 类在此诞生、成长,死亡
- gc垃圾回收主要在伊甸园区和养老区
- 方法区
- 所有方法信息,信息共享;static/final/Class/常量池
- 在堆中,永久区(元空间、非堆)
- PC寄存器
- 线程私有的
- 存储指向下一条指令的地址
类加载器
- 分类,逐层向上查找
- 虚拟机自带加载器
- Bootstrap classLoader:启动类加载器;负责加载核心的类库(java.lang.*等),构造ExtClassLoader和APPClassLoader。
- ExtClassLoader:扩展类加载器;主要负责加载jre/lib/ext目录下的一些扩展的jar。
- AppClassLoader:主要负责加载应用程序的主函数类
- 双亲委派机制
- 不断向上查找,优先使用根级目录中定义的类和方法
- 优点
- 沙箱安全机制,避免核心库被恶意篡改
- 沙箱:限制程序运行的环境;限制程序对系统资源的访问
- 所需组件:字节码校验器、类加载器
- 避免类重复加载
- 沙箱安全机制,避免核心库被恶意篡改
native
- 带有native关键字的方法会进入本地方法栈;登记本地方法
- JNI:java native interface 扩展java的使用,融合不同编程语言
堆内存调优 --> GC
- 轻度清理 GC:只清理新生区,偶尔幸存区 / 重度清理 FULL GC
- 常用算法
- 引用计数器:计数器计数
- 复制算法:作用在新生区;如,当幸存区from和to都有值时,将其中一个复制到另一块,保证有一块是空的
- 好处:没有碎片空间
- 缺点:浪费内存空间;有一半空间永远是空的
- 最佳使用场景:存活度较低的情况 --> 新生区 - 标记清除法:扫描内存后,对没有标记的地址进行清除;
+ 优点:不需要额外的内存空间
+ 缺点:两次扫描浪费时间;会产生内存碎片 - 标记压缩:再次扫描,向一段移动存活对象,防止产生内存碎片;多了移动的成本
- 算法对比
- 内存效率:复制算法 > 标记清除 > 标记压缩
- 内存整齐度:复制算法 = 标记压缩 > 标记清除
- 内存利用率:标记清除 = 标记压缩 > 复制算法
- GC应用:分代收集算法
- 新生代:存活率低 --> 复制算法
- 老年代:区域大,存活率高 --> 标记压缩 + 标记清除
JProfiler工具/MAT
- 作用:
- 分析dump文件,快速定位内存泄露
- 分析堆中的数据
- 获得大的对象
- JProfilter使用步骤
- Idea安装插件plugin,系统安装JProfilter客户端软件(路径不能有空格)
- VM Option中加入代码 -Xms1m -Xmx8m -XX:+HeapDumpOnOutOfMemoryError
- -Xms1m:设置初始化内存大小为1M,默认为系统的1/64
- -Xmx8m:设置最大内存大小为8M,默认为系统的1/4
- -XX:+PrintGCDetails:打印GC清理的信息
- -XX:+HeapDumpOnOutOfMemoryError:打印OOM信息到dump文件
- 在src文件夹中用JProfilter客户端打开dump文件分析即可
JMM Java Memory Model
- 作用:缓存一致性协议,用于定义数据读写的规则
- JMM定义了线程工作内存和主内存之间的抽象关系:线程之间的共享变量存储在主内存Main Memory;每个线程都有一个私有的本地内存Local Memory
- 带来的问题
- 可见性问题:线程内存中的变动没有及时刷新到主内存时,更改不可见
- 解决办法:java关键字volatile或加锁
- 可见性问题:线程内存中的变动没有及时刷新到主内存时,更改不可见